我面临着 JOIN FETCH 和 EAGER 关系的问题。
我有以下实体关系:
实体 A 扩展抽象实体 E。
抽象实体 E 与具有EAGER 提取类型的实体 C 具有 oneToOne 双向关系。
实体 A 与实体 B 具有 oneToMany 关系。
实体 B 扩展了抽象实体 E(因此与 C 也有 oneToOne 关系)
实体 C 与抽象实体 E 具有反比关系
在执行一个简单的namedQuery时
SELECT a FROM A a WHERE a.key = :key
其中参数'key'是String类型,那么我没有问题。从检索到的实体 A 访问子实体 B 按预期执行子请求。
但是,如果我向我的 namedQuery 添加一个 JOIN FETCH:
SELECT a FROM A a JOIN FETCH a.entitiesB WHERE a.key = :key
我获得以下错误堆栈跟踪:
javax.ejb.EJBTransactionRolledbackException: The transaction has been marked rollback only because the bean encountered a non-application exception :javax.ejb.EJBTransactionRolledbackException : The transaction has been marked rollback only because the bean encountered a non-application exception :org.apache.openjpa.persistence.ArgumentException : The specified parameter of type "class org.apache.openjpa.util.LongId" is not a valid query parameter.
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.convertException(BaseEjbProxyHandler.java:345)
at org.apache.openejb.core.ivm.BaseEjbProxyHandler.invoke(BaseEjbProxyHandler.java:283)
...
Caused by: <openjpa-2.2.0-r422266:1244990 nonfatal user error> org.apache.openjpa.persistence.ArgumentException: The specified parameter of type "class org.apache.openjpa.util.LongId" is not a valid query parameter.
FailedObject: SELECT relation FROM Relation relation JOIN FETCH relation.accounts WHERE relation.key = :key [java.lang.String]
at org.apache.openjpa.jdbc.sql.DBDictionary.setUnknown(DBDictionary.java:1458)
at org.apache.openjpa.jdbc.sql.SQLBuffer.setParameters(SQLBuffer.java:544)
at org.apache.openjpa.jdbc.sql.SQLBuffer.prepareStatement(SQLBuffer.java:453)
at org.apache.openjpa.jdbc.sql.SQLBuffer.prepareStatement(SQLBuffer.java:429)
at org.apache.openjpa.jdbc.sql.SelectImpl.prepareStatement(SelectImpl.java:479)
...
如果我将 EAGER 关系更改为 LAZY,则不再出现此错误。所以有什么问题 ?
编辑1:如果我保持oneToOne与LAZY fetch类型的关系并直接在namedQuery上添加JOIN FETCH a.entityC,我会得到同样的错误
编辑 2:从 abstractEntity 类中删除与实体 C 的关系 oneToOne 并将此关系直接添加到 EntityA 和 EntityB 中(加上修改实体 C 以与 A & B 具有反向关系),仍然将此 oneToOne 关系保持为 EAGER => 没问题。所以看起来问题出在将这个共享关系放到抽象实体类中,但为什么呢?
这是说明问题的代码示例。
实体 A
@Entity
@Table(name = "TABLE_A")
@Access(AccessType.FIELD)
@NamedQueries({
@NamedQuery(name = "findADetails", query = "SELECT a FROM A a WHERE a.customKey.key = :customKey")})
public class A extends abstractEntity {
@Embedded
private CustomEmbeddedKey customKey;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "entityA")
private List<B> bEntities;
...
}
实体 B
@Entity
@Table(name = "TABLE_B")
@Access(AccessType.FIELD)
public class B extends abstractEntity {
@ManyToOne(fetch = FetchType.LAZY, targetEntity = A.class)
@JoinColumn(name = "FK_A_ID")
private A entityA;
...
}
抽象实体类
@Entity
@Access(AccessType.FIELD)
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@SequenceGenerator(name = "TOTO_ID_SEQ", sequenceName = "TOTO_ID_SEQ", initialValue = 1, allocationSize = 1)
public abstract class abstractEntity {
@Id
@Column(name = "ID")
@GeneratedValue(generator = "TOTO_ID_SEQ", strategy = GenerationType.SEQUENCE)
private Long id;
@OneToOne(mappedBy = "...", fetch = FetchType.EAGER)
private C anotherEntity;
@OneToMany(mappedBy = "...", fetch = FetchType.LAZY)
private List<D> anotherEntities;
...
}
嵌入式密钥
@Embeddable
@Access(AccessType.FIELD)
public class CustomEmbeddedKey {
@Column(name = "...", length = ...)
private String key;
...
}
刀样
TypedQuery<A> query = createNamedQuery("findADetails", A.class);
query.setParameter("customKey", queryParam);
List<A> aEntitiesFound = query.getResultList();
在此先感谢您的帮助。