我正面臨JOIN FETCH和EAGER關係的問題。JPA ArgumentException在EAGER共享關係上執行JOIN FETCH時發生錯誤oneToOne
我有以下實體關係:
實體A擴展抽象的實體E.
摘要實體E具有與實體下的oneToOne雙向關係與預先抓取類型。
實體A與實體B.
實體B一對多關係延伸抽象實體E(所以具有以C oneToOne關係太)
實體C具有相反的關係,以抽象的實體È
雖然執行一個簡單的命名查詢如
SELECT a FROM A a WHERE a.key = :key
其中參數'key'是字符串類型,那麼我沒有問題。從檢索到的實體A訪問子實體B按照其假定的那樣執行子請求。
但是,如果我添加一個連接抓取到我的namedQuery:
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關係懶,我沒有這個錯誤了。所以有什麼問題 ?
編輯1:我得到同樣的錯誤,如果我繼續oneToOne關係與LAZY獲取類型,並添加直接加入的namedQuery FETCH a.entityC
編輯2:從abstractEntity類實體Ç刪除關係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();
在此先感謝您的幫助。