| If I am not mistaken, I am hitting this same issue (in 4.3.11.Final). This is a significant roadblock for properly specifying eager loading (at query time, not at mapping time) and I haven't been able to find a workaround. As for the test, here's the minimum code to reproduce. Super.java
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Super {
private String id;
private Super a;
@Id
public String getId() { return id; }
public void setId(String id) { this.id = id; }
@ManyToOne
public Super getA() { return a; }
public void setA(Super a) { this.a = a; }
}
Sub.java
import javax.persistence.Entity;
@Entity
public class Sub extends Super {}
Actual test:
private void testHHH10378(EntityManager entityManager) {
EntityGraph<Super> graph = entityManager.createEntityGraph(Super.class);
graph.addSubgraph("a", Sub.class);
}
This fails with:
Specifically the cause is likely the isTreatableAs() method in AttributeNodeImpl. Even its JavaDoc description is self-conflicting - the first sentence is exactly opposite of the second one... and the implementation follows the first one. For convenience, here's that method:
/**
* Check to make sure that the java type of the given entity persister is treatable as the given type. In other
* words, is the given type a subclass of the class represented by the persister.
*
* @param entityPersister The persister to check
* @param type The type to check it against
*
* @return {@code true} indicates it is treatable as such; {@code false} indicates it is not
*/
@SuppressWarnings("unchecked")
private boolean isTreatableAs(EntityPersister entityPersister, Class type) {
return type.isAssignableFrom( entityPersister.getMappedClass() );
}
Note the two conflicting descriptions:
- Check to make sure that the java type of the given entity persister is treatable as the given type.
- In other words, is the given type a subclass of the class represented by the persister.
(1) means "the given entity persister is a subtype of the given type", whereas (2) means that the "given type is a subclass of the class represented by the persister". |