michal.jakubeczy
michal.jakubeczy

Reputation: 9469

Hibernate - rewrite legacy createCriteria

I have a following Hibernate code:

        return (Post)sessionFactory.getCurrentSession()
                .createCriteria(Post.class)
                .add(Restrictions.eq("title", title))
                .add(Restrictions.eq("description", description))
                .uniqueResult();

But the method createCriteria is deprecated. How to rewrite it to CriteriaQuery so the code remains minimalistic and without the use of CriteriaBuilder.

Upvotes: 3

Views: 1832

Answers (1)

VHS
VHS

Reputation: 10184

The Hibernate 5.4 docs recommend usage of Jakarta Persistence API (JPA) classes under javax.persistence.criteria package wherever we were using Hibernate's SharedSessionContract.createCriteria(java.lang.Class) method. In fact all the methods including the overloads of the method createCriteria that returned org.hibernate.Criteria are deprecated, which indirectly means that Hibernate doesn't want us to use their org.hibernate.Criteria interface anymore. In version 5.4, there is no implementing class or extending interface for the Criteria interface. In short, the hibernate Session that used to act as a factory for Criteria objects no longer produces them and Criteria might be fully deprecated in future versions.

Secondly, Hibernate offered useful API under the package org.hibernate.criterion e.g. Restrictions, Example, etc. The problem is that all of these classes seem to have only one consumer class of type org.hibernate.Criteria which is being deprecated. In other words, if you can't use org.hibernate.Criteria, you can't use org.hibernate.criteria.Restrictions either.

In summary, if you have to refactor your above code now, your only choice is what you have under javax.persistence.criteria. Therefore, your only choice is to use CriteriaBuilder and CreateQuery as shown below.

CriteriaBuilder cb = sessionFactory.getCurrentSession().getCriteriaBuilder();

// Create query
CriteriaQuery<Post> q = cb.createQuery(Post.class)
Root<Post> r = q.from(Post.class);

Predicate[] predicates = new Predicate[2];
predicates[0] = cb.equal(root.get("title"), title);
predicates[1] = cb.equal(root.get("description"), description);

q.select(r).where(predicates);
Query<Post> query = session.createQuery(q);
return query.getSingleResult();

Yes, this code is quite verbose compared to your original code using Hibernate API. However, one advantage this code offers is that it is now decoupled from Hibernate specific API. So in future if you want to migrate to another JPA implementation, you wouldn't have to change your code.

Upvotes: 3

Related Questions