Reputation: 113
I have a class structure like this:
@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;
}
I tried the following to receive all CartItems
that have a reference to a Book
with title = 'Foo'
:
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();
But unfortunately, this results in an error (makes sense to me, as title
is in Book
, not in 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) ...
However, I was able to achieve what I want using the following HQL:
SELECT c, a FROM CartItem c INNER JOIN c.article a WHERE a.title = ?
So why does the latter work and can I achieve something similar using the Criteria API?
Upvotes: 10
Views: 9401
Reputation: 6660
I had the same issue and found a solution thanks to chris (see JPA Criteria API where subclass).
For this you need JPA 2.1, and you make use of one of the CriteriaBuilder.treat()
methods. Just replace your builder.equal...
line by:
builder.equal(builder.treat(root.get("article"), Book.class).get("title"), "Foo");
Upvotes: 4
Reputation: 725
I'm not an expert but from an OO point of view I would say that an Article does not have a property title and is therefore not found on the CarItem's property named article.
Maybe you should check if Article is of type Book.
I'm not sure how to do this using CriteriaBuilder
Criteria c=session.createCriteria(CarItem.class, "caritem");
c.add(Restrictions.eq("caritem.class", Book.class));
List<Article> list=c.list();
Upvotes: 1