If HQL supports all the features you need for your query. Like, any complex query at all. Note the phrasing “certain joins”. Need to build a search query dynamically and still load all the joined tables into your object tree with a single roundtrip? Have fun fiddling around with the criteria API and using the correct join/fetch methods. Need to join multiple many-to-many relationships efficiently (i.e. one top-level query and then one query per relationship instead of one explosive join or N+1 queries)? Enjoy writing all of that logic yourself and fighting the entity cache (with pseudo queries that don’t actually hit the DB and are only there to make Hibernate link the cached entities). Because Hibernate can’t fucking figure it out. With Django it’s always prefetch_related(list of navigational properties) and you’re done. No matter if it’s one relationship or 100, one nesting level or 10, Django picks the right join strategy for you. When I used Hibernate with Spring there were so many situations where I would have preferred to use the underlying EntityManager directly, but that’s not what all the default Spring patterns want you to do, so you choose between fighting Spring or fighting Hibernate.
Also, if you have to resort to HQL you’re basically falling back to SQL in my book. The whole point of ORMs is to not write query boilerplate.
When I used Hibernate with Spring there were so many situations where I would have preferred to use the underlying EntityManager directly, but that’s not what all the default Spring patterns want you to do, so you choose between fighting Spring or fighting Hibernate.
You literally just inject the EntityManager:
@Service
public class AccountService {
private final EntityManager entityManager;
public AccountService(EntityManager entityManager) {
this.entityManager = entityManager;
}
@Transactional
public void doSomething(Long accountId) {
Account account = entityManager.find(Account.class, accountId);
// use entityManager...
}
}
The whole point of ORMs is to not write query boilerplate.
That is not the even remotely the point of ORMs. The point is right in the name Object Relationship Mapper. Its sole purpose to map resultsets to objects.
Need to build a search query dynamically and still load all the joined tables into your object tree with a single roundtrip? Have fun fiddling around with the criteria API and using the correct join/fetch methods. Need to join multiple many-to-many relationships efficiently (i.e. one top-level query and then one query per relationship instead of one explosive join or N+1 queries)?
Just drop down to native SQL. Hibernate will still map your result set to an object.
Sure, now you have to create a custom repo implementation instead of the default way of using repo inferfaces with the method name DSL.
I didn’t say Spring+Hibernate can’t do these things. It’s just that the convenient low-boilerplate parts are extremely limited and doing anything slightly more complex instantly requires you to study the intricacies of the session context and how Spring interferes with that, or create several classes just because you wanted a single join strategy that wasn’t covered by the defaults despite being pretty standard and that would have been a single line with django.
I wish I could give you more specifics, but that experience was 2 years ago and I don’t have access to the code anymore. What burned itself into my memory was how ridiculously troublesome it was to get a query over three 1:n relations including a recursive one (a tree) with a few transitive 1:1 relations working as its supposed to (no combinatorial explosion, no additional N queries when processing the result set and accessing navigational properties).
My entire point is: If it’s this annoying to write efficient queries, many developers will simply not care. They will use their simple generated repo method and be done with it because N+1 queries probably won’t be prohibitively bad in many situations (and I’ve even heard one saying the Hibernate cache figures that out automatically anyway and they won’t try to be smarter than the ORM, vastly overestimating what Hibernate does in this case by default).
-1
u/wildjokers 7d ago
You literally just write a join in HQL. There are no hoops to jump through.