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?
Let's see it step by step: Create an instance of Session from the SessionFactory object. Create an instance of CriteriaBuilder by calling the getCriteriaBuilder() method. Create an instance of CriteriaQuery by calling the CriteriaBuilder createQuery() method.
The Criteria API is a predefined API used to define queries for entities. It is the alternative way of defining a JPQL query. These queries are type-safe, and portable and easy to modify by changing the syntax. Similar to JPQL it follows abstract schema (easy to edit schema) and embedded objects.
Criteria in Hibernate API can be used for fetching results with conditions, useful methods are add() where we can add Restrictions. Hibernate Criteria API provides addOrder() method that we can use for ordering the results.
The type of a simple or compound predicate: a conjunction or disjunction of restrictions. A simple predicate is considered to be a conjunction with a single conjunct. Since: Java Persistence 2.0.
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");
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With