JPA Criteria API:子类的查询属性

时间:2011-08-01 20:03:37

标签: sql hibernate jpa polymorphism criteria

我有这样的类结构:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Article {
   private String aBaseProperty;
}

@Entity
public class Book extends Article {
   private String title;
}

@Entity
public class CartItem {
   @ManyToOne(optional = false)
   public Article article;
}

我尝试了以下操作来接收所有引用CartItemsBook title = 'Foo'的{​​{1}}:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<CartItem> query = builder.createQuery(CartItem.class);
Root<CartItem> root = query.from(CartItem.class);
builder.equal(root.get("article").get("title"), "Foo");
List<CartItem> result = em().createQuery(query).getResultList();

但不幸的是,这会导致错误(对我来说很有意义,因为title位于Book,而不是Article ......):

java.lang.IllegalArgumentException: Could not resolve attribute named title
    at org.hibernate.ejb.criteria.path.SingularAttributePath.locateAttributeInternal(SingularAttributePath.java:101)
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.locateAttribute(AbstractPathImpl.java:216)
    at org.hibernate.ejb.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:189)
...

但是,我能够使用以下HQL实现我想要的目标:

SELECT c, a FROM CartItem c INNER JOIN c.article a WHERE a.title = ?

那么为什么后者有效呢?我可以使用Criteria API实现类似的东西吗?

2 个答案:

答案 0 :(得分:1)

我不是专家,但从OO的角度来看,我会说文章没有属性标题,因此在CarItem的属性命名文章中找不到。

也许您应该检查文章是否为Book类型。

我不知道如何使用CriteriaBuilder

来做到这一点
Criteria c=session.createCriteria(CarItem.class, "caritem");
c.add(Restrictions.eq("caritem.class", Book.class));
List<Article> list=c.list();

答案 1 :(得分:1)

我遇到了同样的问题,感谢chris找到了解决方案(参见JPA Criteria API where subclass)。

为此你需要JPA 2.1,并且你使用了CriteriaBuilder.treat()方法之一。只需将您的builder.equal...行替换为:

builder.equal(builder.treat(root.get("article"), Book.class).get("title"), "Foo");