We have several old projects mostly JEE and some new ones with SpringBoot (which we’re actually migrating to SpringBoot 2).
First you are right @Naros. Spring Data (especially the autogenerated repositories) take a lot of the pain.
But apart from that we also have many much heavier queries. I just copied one (very simple) example from our code (even without any join or special fetch):
Session hibernateSession = entityManager.unwrap(org.hibernate.Session.class);
Criteria criteria = hibernateSession.createCriteria(DS.class);
criteria.add(Restrictions.or(
Restrictions.isNull("bereitgestelltfuer"),
Restrictions.eq("bereitgestelltfuer", kunde)
));
criteria.add(Restrictions.eq("ism", ism));
criteria.add(Restrictions.eq("status", BEREITGESTELLT));
if (since != null) criteria.add(Restrictions.gt("created", since));
if (dsType != null) criteria.add(Restrictions.eq("type", dsType));
criteria.addOrder(Order.asc("created"));
List<DS> result1 = criteria.list();
The code is so nice to read and to write. Written in Kotlin with static imports it looks nearly perfect which means that there is no technical stuff around, but only the key information that are required to understand the query:
val list = session.createCriteria(DS::class.java).apply {
add(or(isNull("bereitgestelltfuer"), eq("bereitgestelltfuer", kunde)))
add(eq("ism", ism))
add(eq("status", BEREITGESTELLT))
if (since != null) add(gt("created", since))
if (dsType != null) add(eq("type", dsType))
addOrder(asc("created"))
}.list() as List<IDS>
I just tried to convert it to JPA to show the difference (without meta modell). I’m not sure if it could be done better or if it’s maybe even wrong:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(DS.class);
Root<DS> root = query.from(DS.class);
List<Predicate> conditions = new ArrayList<>();
ParameterExpression<Kunde> kundeParameter = cb.parameter(Kunde.class);
conditions.add(cb.or(
cb.isNull(kundeParameter),
cb.equal(root.<Kunde>get("bereitgestelltfuer"), kundeParameter)
));
conditions.add(cb.equal(root.<ISM>get("ism"), ism));
conditions.add(cb.equal(root.<DSStatus>get("status"), BEREITGESTELLT));
if (since != null) conditions.add(cb.greaterThan(root.<Date>get("created"), since));
if (dsType != null) conditions.add(cb.equal(root.<String>get("created"), dsType));
CriteriaQuery finalQuery = query
.select(root)
.where(conditions.toArray(new Predicate[conditions.size()]))
.orderBy(cb.asc(root.<Date>get("created")));
List<QLDS> result2 = entityManager.createQuery(finalQuery).getResultList();
}
I think JPA criteria has the very clear focus to be type safe. Other points (like readability) were placed behind. The concepts are completely different. That is also the reason why I don’t think it is a good idea to start working on JPA (@vlad).
but I cannot tell you how may times I have run into issues where a developer changed the entity model but missed a reference to a property somewhere or just out-right had a typo
This on the other side is something we nearly never see due to a lot of unit tests and the refactoring power of IntelliJ.
With some time (and maybe one or two beers) you could see here a very general discussion about the heavyweight, slow changing but also very thoughtful JEE APIs vs. lightweight APIs of other frameworks. One of the strengths of hibernate is that is serves both very well.