Polymorphic CriteriaQuery没有反比关系

我有以下EJB结构。 不要怀疑AnimalInventory ,这些类只是在这里以简化的方式演示结构( 更新 :我修改了类名以构造一个更好理解的例子IdTag另一个实现可能是BarcodeId )。 请注意, IdTagAnimalInventory之间没有反向关系,我们假设RfidTag.code是唯一的。 我阅读了使用Criteria Query和Hibernate多态查询 检索多态Hibernate对象 ,但这些讨论似乎没有回答我的问题。

 public interface ItemWithIdTag { IdTag getIdTag(); void setIdTag(IdTag idTag); } @Entity public class Animal implements ItemWithIdTag,Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; @OneToOne(cascade = CascadeType.ALL) private IdTag idTag; } @Entity public class Inventory implements ItemWithIdTag,Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; @OneToOne(cascade = CascadeType.ALL) private IdTag idTag; } @Entity @Table(name = "IdTag") @Inheritance(strategy= InheritanceType.JOINED) public class IdTag implements Serializable { @Id @GeneratedValue(strategy=GenerationType.AUTO) private long id; private Date created; } @Entity @Table(name = "RfidTag") public class RfidTag extends IdTag implements Serializable { private String code; } 

现在我想查询AnimalInventory给定的RfidTag.codeAnimal ejb = bean.fEntityWithRfidTag(Animal.class,"myRfIdCode");

 public  T fOwner(Class type, String catName) { CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(type); Root from = criteriaQuery.from(type); Path path = from.join("idTag").get("code"); CriteriaQuery select = criteriaQuery.select(from); select.where(criteriaBuilder.equal(path, catName)); TypedQuery q = em.createQuery(select); T result = (T)q.getSingleResult();} return result; } 

不幸的是我得到以下错误:

 javax.ejb.EJBException: java.lang.IllegalArgumentException: Unable to resolve attribute [code] against path [null] 

我假设这与inheritanceIdTag相关 – > RfidTagAnimal只知道IdTag而不是RfidTag.code 。 这样的查询可能吗?

如果您使用的是EclipseLink,解决方案很简单。 修改路径条件以强制转换为RfIdTag:

 Path path = ((Path) from.join("idTag").as(RfIdTag.class)).get("code"); 

如果您使用的是Hibernate,请将您的方法替换为:

 public static  T fOwner(Class type, String catName) { CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(type); Root fromType = criteriaQuery.from(type); Root fromRfId = criteriaQuery.from(RfIdTag.class); Path pathCode = fromRfId.get("code"); Path pathIdTagType = fromType.get("idTag"); Path pathIdTagRfId = fromRfId.get("id"); CriteriaQuery select = criteriaQuery.select(fromType); select.where( criteriaBuilder.equal(pathCode, catName), criteriaBuilder.equal(pathIdTagType, pathIdTagRfId)); TypedQuery q = em.createQuery(select); return q.getSingleResult(); } 

这在“T”和“RfIdTag”之间产生“连接”(“过滤的笛卡尔积”)。