I'm facing a problem with JOIN FETCH and EAGER relations.
I have the following entity relations:
Entity A extends abstract entity E.
Abstract entity E has a oneToOne bidirectional relation with Entity C with EAGER fetch type.
Entity A has oneToMany relation with Entity B.
Entity B extends abstract entity E (so have oneToOne relation too with C)
Entity C has inverse relation to abstract entity E
While executing a simple namedQuery like
SELECT a FROM A a WHERE a.key = :key
Where parameter 'key' is String type, then i have no problem. Accessing to sub entities B from retrieved entity A execute sub requests as its supposed to be.
But if i add a JOIN FETCH to my namedQuery:
SELECT a FROM A a JOIN FETCH a.entitiesB WHERE a.key = :key
i obtain the following error stack trace:
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)
...
If i change the EAGER relations to LAZY, i do not have this error anymore. So, what's the problem ?
Edit 1: I get the same error if i keep oneToOne relations with LAZY fetch type and add JOIN FETCH a.entityC directly on the namedQuery
Edit 2: Removing relation oneToOne with entity C from abstractEntity class and adding this relation directly into EntityA and EntityB (plus modifying entity C to have reverse relation with A & B), still keeping this oneToOne relation as EAGER => No problem. So it looks like the problem come from having this shared relation into the abstract entity class, but why?
This is code example illustrated the problem.
Entity 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;
...
}
Entity 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;
...
}
Abstract entity class
@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;
...
}
Embedded key
@Embeddable
@Access(AccessType.FIELD)
public class CustomEmbeddedKey {
@Column(name = "...", length = ...)
private String key;
...
}
Dao sample
TypedQuery<A> query = createNamedQuery("findADetails", A.class);
query.setParameter("customKey", queryParam);
List<A> aEntitiesFound = query.getResultList();
Thanks in advance for your help.