我有以下具有自關聯的引數物體,我正在嘗試進行單元測驗來檢查我的實作,但感覺我在映射中犯了一些錯誤,我無法檢測到我在哪里弄錯了。
我的物體如下
import java.io.Serializable;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import com.tuto.common.enums.ParameterCategory;
import com.tuto.common.enums.ParameterType;
import com.tuto.common.enums.converter.ParameterTypePersistenceConverter;
/**
* This class represents the PARAMETERS SQL table as a java entity.
*
*/
@Entity
@Table(name = "PARAMETERS")
public class Parameter implements Serializable {
/**
* serialVersionUID.
*/
private static final long serialVersionUID = -732987999122243011L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SQ_PARAMETER_ID")
@SequenceGenerator(name = "SQ_PARAMETER_ID", sequenceName = "SQ_PARAMETER_ID", allocationSize = 1)
@Column(name = "PARAMETER_ID", unique = true)
private long id;
@Column(name = "PARAMETER_NAME")
private String name;
@Column(name = "PARAMETER_LABEL")
private String label;
@Column(name = "PARAMETER_COMMENT")
private String comment;
@JoinColumn(name = "ES_ID")
@OneToOne(fetch = FetchType.LAZY)
private ExpertSystem expertSystem;
@Column(name = "PARAMETER_CATEGORY")
@Enumerated(EnumType.ORDINAL)
private ParameterCategory category;
@Column(name = "PARAMETER_TYPE")
@Convert(converter = ParameterTypePersistenceConverter.class)
private ParameterType type;
@Column(name = "PARAMETER_CREATION_DATE",columnDefinition = "TIMESTAMP")
private OffsetDateTime creationDate;
@JoinColumn(name = "PARAMETER_CREATION_USER",referencedColumnName = "USER_FIRSTNAME")
@OneToOne(fetch = FetchType.LAZY)
private User creationUser;
@Column(name = "PARAMETER_UPDATE_DATE",columnDefinition = "TIMESTAMP")
private OffsetDateTime updateDate;
@JoinColumn(name = "PARAMETER_UPDATE_USER",referencedColumnName = "USER_FIRSTNAME")
@OneToOne(fetch = FetchType.LAZY)
private User updateUser;
@Column(name = "MULTIVALUE_SIZE")
private int multivalueSize;
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "dependences",
joinColumns = {@JoinColumn(name ="PARAMETER_ID")},
inverseJoinColumns = {@JoinColumn(name ="DEPENDANCE_ID")})
private List<Parameter> dependences = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY)
@JoinTable(name = "dependences",
joinColumns = {@JoinColumn(name ="DEPENDANCE_ID")},
inverseJoinColumns = {@JoinColumn(name ="PARAMETER_ID")})
private List<Parameter> consequences = new ArrayList<>();
public Parameter() {}
public Parameter(long id, String name, String label, String comment, ExpertSystem expertSystem,
ParameterCategory category, ParameterType parameterType, OffsetDateTime creationDate, User creationUser,
OffsetDateTime updateDate, User updateUser, int multivalueSize,List<Parameter> dependences) {
super();
this.id = id;
this.name = name;
this.label = label;
this.comment = comment;
this.expertSystem = expertSystem;
this.category = category;
this.type = parameterType;
this.creationDate = creationDate;
this.creationUser = creationUser;
this.updateDate = updateDate;
this.updateUser = updateUser;
this.multivalueSize = multivalueSize;
this.dependences = dependences;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public ExpertSystem getExpertSystem() {
return expertSystem;
}
public void setExpertSystem(ExpertSystem expertSystem) {
this.expertSystem = expertSystem;
}
public ParameterCategory getCategory() {
return category;
}
public void setCategory(ParameterCategory category) {
this.category = category;
}
public ParameterType getType() {
return type;
}
public void setType(ParameterType parameterType) {
this.type = parameterType;
}
public OffsetDateTime getCreationDate() {
return creationDate;
}
public List<Parameter> getDependences() {
return dependences;
}
public List<Parameter> getConsequences() {
return consequences;
}
public void setCreationDate(OffsetDateTime creationDate) {
this.creationDate = creationDate;
}
public User getCreationUser() {
return creationUser;
}
public void setCreationUser(User creationUser) {
this.creationUser = creationUser;
}
public OffsetDateTime getUpdateDate() {
return updateDate;
}
public void setUpdateDate(OffsetDateTime updateDate) {
this.updateDate = updateDate;
}
public User getUpdateUser() {
return updateUser;
}
public void setUpdateUser(User updateUser) {
this.updateUser = updateUser;
}
public int getMultivalueSize() {
return multivalueSize;
}
public void setMultivalueSize(int multivalueSize) {
this.multivalueSize = multivalueSize;
}
public void setDependences(List<Parameter> dependences) {
this.dependences = dependences;
}
public void setConsequences(List<Parameter> consequences) {
this.consequences = consequences;
}
public void addDependence(Parameter dependence) {
if(dependence != null ) {
removeConsequence(dependence);
this.dependences.add(dependence);
dependence.getConsequences().add(this);
}
}
public void removeDependence(Parameter dependence) {
if(dependence != null && this.dependences.contains(dependence) ) {
final int indexOfConsequence = this.dependences.indexOf(dependence);
Parameter parameter = this.dependences.get(indexOfConsequence) ;
parameter.getDependences().remove(this);
}
}
public void addConsequence(Parameter consequence) {
if(consequence != null ) {
removeConsequence(consequence);
this.consequences.add(consequence);
consequence.getDependences().add(this);
}
}
public void removeConsequence(Parameter consequence) {
if(consequence != null && this.consequences.contains(consequence) ) {
final int indexOfConsequence = this.consequences.indexOf(consequence);
Parameter parameter = this.consequences.get(indexOfConsequence) ;
parameter.getDependences().remove(this);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result (int) (id ^ (id >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Parameter other = (Parameter) obj;
if (id != other.id)
return false;
return true;
}
@Override
public String toString() {
return "Parameter [id=" id ", name=" name ", label=" label ", comment=" comment
", expertSystem=" expertSystem ", category=" category ", type=" type
", creationDate=" creationDate ", creationUser=" creationUser ", updateDate=" updateDate
", updateUser=" updateUser ", multivalueSize=" multivalueSize ", dependences=" dependences "]";
}
}
我的存盤庫如下所示
import java.util.List;
import org.springframework.data.jpa.repository.EntityGraph;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.tuto.entity.Parameter;
/**
* This interface defines the contract of the possible operations to manage the parameter entity in the database.
*
*/
@Repository
public interface IParameterRepository extends JpaRepository<Parameter, Long> {
/**
* This method fetches the list of all available parameters. It could return an empty list.
*
* @return List<Parameter> The list of all Parameters found
*/
@Transactional
@Modifying(clearAutomatically = false)
@Query(value = "SELECT param FROM Parameter param")
List<Parameter> getAllParameters();
/**
* This method fetches the dependencies list (as Parameter list) for the given Param id.
* It could return an empty list.
*
* @param idParam The id of Parameter.
* @return List<Parameter> The dependencies list (as Parameter list) found for the given Param id.
*/
@Transactional
@Modifying(clearAutomatically = false)
@EntityGraph(attributePaths = {"dependences","expertSystem"})
@Query(value = "SELECT param.dependences FROM Parameter param join fetch param.dependences where param.id = :#{#idParam} ", nativeQuery = false)
List<Parameter> getDependancesByParamId(final long idParam);
/**
* This method fetches the consequences list (as Parameter list) for the given Param id.
* It could return an empty list.
*
* @param idParam The id of Parameter.
* @return List<Parameter> The dependencies list (as Parameter list) found for the given Param id.
*/
@Transactional
@Modifying(clearAutomatically = false)
@EntityGraph(attributePaths = {"consequences","expertSystem"})
@Query(value = "SELECT param.consequences FROM Parameter param join fetch param.consequences where param.id = :#{#idParam} ", nativeQuery = false)
List<Parameter> getConsequencesByParamId(final long idParam);
}
我的單元測驗如下
import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
import org.springframework.test.context.ActiveProfiles;
import com.tuto.common.enums.ParameterCategory;
import com.tuto.common.enums.ParameterType;
import com.tuto.entity.Parameter;
import com.tuto.core.profile.PfSpringProfiles;
import com.tuto.test.Tags;
@DataJpaTest(showSql = true)
@Tag(Tags.COMPONENT)
@ActiveProfiles(PfSpringProfiles.TEST)
public class ParameterRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private IParameterRepository parameterRepository;
@BeforeEach
public void intTests() {
final Parameter parameterInput = new Parameter();
parameterInput.setCategory(ParameterCategory.INPUT);
parameterInput.setType(ParameterType.DECIMAL);
parameterInput.setId(1L);
final Parameter parameterIntermediate = new Parameter();
parameterIntermediate.setCategory(ParameterCategory.INTERMEDIATE);
parameterIntermediate.setType(ParameterType.DECIMAL);
parameterIntermediate.setId(2L);
final Parameter parameterOutput = new Parameter();
parameterOutput.setCategory(ParameterCategory.OUTPUT);
parameterOutput.setType(ParameterType.DECIMAL);
parameterOutput.setId(3L);
entityManager.merge(parameterInput);
entityManager.merge(parameterIntermediate);
entityManager.merge(parameterOutput);
// parameterInput.getConsequences().add(parameterIntermediate);
parameterInput.addConsequence(parameterIntermediate);
parameterIntermediate.addConsequence(parameterOutput);
// parameterIntermediate.getConsequences().add(parameterOutput);
// parameterOutput.getDependences().add(parameterIntermediate);
// parameterIntermediate.getDependences().add(parameterInput);
entityManager.merge(parameterOutput);
entityManager.merge(parameterIntermediate);
entityManager.merge(parameterInput);
}
@Test
public void checkConsequencesAndDependencesAreNotEmpty() {
List<Parameter> parameter = parameterRepository.getDependancesByParamId(2L);
assertEquals(parameter.size(),1);
assertEquals(parameter.get(0).getId(),1L);
}
}
我面臨兩個例外:第一個是著名的持久分離物體,另一個是查詢指定的連接提取,但提取關聯的所有者不在選擇串列中
全堆疊跟蹤
Caused by: java.lang.IllegalArgumentException: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=com.tuto.entity.Parameter.consequences,tableName=parameters,tableAlias=parameter2_,origin=parameters parameter0_,columns={parameter0_.parameter_id,className=com.tuto.entity.Parameter}}] [SELECT param.consequences FROM com.tuto.entity.Parameter param join fetch param.consequences where param.id = :__$synthetic$__1 ]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:138)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:757)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:114)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:362)
at com.sun.proxy.$Proxy140.createQuery(Unknown Source)
at org.springframework.data.jpa.repository.query.SimpleJpaQuery.validateQuery(SimpleJpaQuery.java:90)
... 88 common frames omitted
Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=com.tuto.entity.Parameter.consequences,tableName=parameters,tableAlias=parameter2_,origin=parameters parameter0_,columns={parameter0_.parameter_id,className=com.tuto.entity.Parameter}}] [SELECT param.consequences FROM com.tuto.entity.Parameter param join fetch param.consequences where param.id = :__$synthetic$__1 ]
at org.hibernate.QueryException.generateQueryException(QueryException.java:120)
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:220)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:144)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:113)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:73)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:162)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:636)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:748)
... 96 common frames omitted
Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list [FromElement{explicit,not a collection join,fetch join,fetch non-lazy properties,classAlias=null,role=com.tuto.entity.Parameter.consequences,tableName=parameters,tableAlias=parameter2_,origin=parameters parameter0_,columns={parameter0_.parameter_id,className=com.tuto.entity.Parameter}}]
at org.hibernate.hql.internal.ast.tree.SelectClause.initializeExplicitSelectClause(SelectClause.java:215)
at org.hibernate.hql.internal.ast.HqlSqlWalker.useSelectClause(HqlSqlWalker.java:1028)
at org.hibernate.hql.internal.ast.HqlSqlWalker.processQuery(HqlSqlWalker.java:796)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:694)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:330)
at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:278)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:276)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:192)
... 102 common frames omitted
uj5u.com熱心網友回復:
我確實解決了這個問題,但我仍然面臨一些審問,如下所示:
修復
@Transactional
@Modifying(clearAutomatically = false)
// @EntityGraph(attributePaths = {"dependences","expertSystem"})
@Query(value = "SELECT param.dependences FROM Parameter param where param.id = :#{#idParam} ", nativeQuery = false)
List<Parameter> getDependancesByParamId(final long idParam);
/**
* This method fetches the consequences list (as Parameter list) for the given Param id.
* It could return an empty list.
*
* @param idParam The id of Parameter.
* @return List<Parameter> The dependances list (as Parameter list) found for the given Param id .
*/
@Transactional
@Modifying(clearAutomatically = false)
// @EntityGraph(attributePaths = {"consequences","expertSystem"})
@Query(value = "SELECT param.consequences FROM Parameter param where param.id = :#{#idParam} ", nativeQuery = false)
List<Parameter> getConsequencesByParamId(final long idParam);
我相信也許選擇param.consequences的物體元素將幫助我避免獲取此集合,但是每個 ExpertSystem 物體元素呢,這是使用延遲加載機制,我不應該能夠從收藏。物體圖也不應該通過自動獲取集合或子元素來幫助我避免這個問題!!!
您可以根據此鏈接重現此實驗
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/473251.html
下一篇:CteInsertStrategy只能與支持CTE的方言一起使用,這些方言也可以采用UPDATE或DELETE陳述句
