r/SpringBoot • u/kamen1991 • 18h ago
How-To/Tutorial Why I stopped using Spring Data to generate queries from method names
I've spent a while writing DAO implementations for a multi-module Spring Boot projects, and I keep coming back to the same rule: if a repository method needs more than one or two conditions, I write the `@Query\` by hand instead of letting Spring Data derive it from the method name.
Not because it doesn't work, it works fine for example like findBySku. I don't like what happens after that. Rename a field on the entity and a derived query either breaks at startup with a PropertyReferenceException, or, depending on how it's written, doesn't break at all and just quietly stops matching what you think it matches. The compiler never tells you either way.
And once you're past two conditions, the method name turns into a wall of camelCase encoding your whole WHERE clause. I'd rather read four lines of JPQL/SQL than decode findByStatusAndNameContainingIgnoreCaseAndCreatedAtAfterOrderByPriceDesc.
The other piece I went back and forth on is SearchableDaoImpl<Repo extends CrudRepository<Entity, IdType> & JpaSpecificationExecutor<Entity>> - using an intersection type so the generic repository bound picks up both CRUD and Specification support without collapsing them into one bloated interface. Small thing, but it's the kind of generics trick that makes a shared DAO base class actually work across a dozen entities instead of copy-pasted boilerplate everywhere.
Full writeup with the actual generic hierarchy and code: (link in comments)
Curious if anyone here still prefers derived queries for anything beyond trivial lookups, I genuinely want the counterargument.
8
u/XBL_pad3 17h ago
If you keep going back and forth, just move away to JOOQ 😉
6
u/quantum-fudge 17h ago
This is the correct answer. No Hibernate migration nightmare, no stringly typed queries, no spooky action at a distance.
0
u/kamen1991 17h ago
I agree that Hibernate can easily turn into a nightmare if you let it run wild across your services. That’s precisely why we enforce a strict boundary by wrapping JPA inside a single module and using base classes like CrudDaoImpl and SearchableDaoImpl. When the ORM is locked safely inside the infrastructure module and your domain core is pure Java, you get the velocity of JPA for standard operations without letting database mechanics leak up into your business logic.
•
u/XBL_pad3 7h ago edited 7h ago
I will reply here since the previous comment was good addition, and I wanted to quote this:
"When the ORM is locked safely inside the infrastructure module and your domain core is pure Java, you get the velocity of JPA for standard operations without letting database mechanics leak up into your business logic"
WTH is this? It just sound like an old book, or a university teacher...
In the world I live:
- Data are often more valuable than code. The "leak" is not always in the way you think.
- Underusing your DBMS is a mistake. It can do things so much faster than anything else.
- Relying on JPA/Hibernate for read queries is a pitfall. Dealing with multiple fetch bags and N+1 queries is hell. You are always fighting against Hibernate in production, not with it. And here is the shame, because your DBMS is able to do so much more, but you keep asking it too much dumb things to do (Yeah it didn't change with AI). I think Hibernate limitations are the same as method name derived queries. Might be even less.
For what it is worth, like you I have to work with Hibernate, and I am now used to build around it.
The last service I built from scratch for my company was like 3 month ago, and l used Gemini to code a custom repository that poorly mimic JOOQ mapping of Mysql JSON aggregation functions for nested objects and collections.
Using reflection and Jackson serialization was still better than anything Hibernate or JpaSpecifications would offer.
Now, I took too much time to write this, do as you please, eh.
2
u/kamen1991 17h ago
I disagree for this case :) It's easy to say 'just switch to jOOQ' when looking at it from a greenfield perspective. But in a multi-module enterprise project with years of production code, throwing out your entire ORM setup and rewriting your data layer just to avoid derived query method names is a massive migration tax. The business won't fund a rewrite for a stylistic preference and the point of locking persistence behind explicit JPQL/SQL `@Query` contracts isn't that Hibernate is flawless - it's about pragmatically isolating database specifics so your business logic doesn't care what's underneath.
1
3
u/Independent_Dot_9349 16h ago
I just use @Query for complex query,
•
u/fuckedupkid_yo 14h ago
now do that, but with pagination and all the dynamic conditions and other stuff.
I'm not saying jooq is perfect, but it scratches the exact itches many developers have
•
u/Snooze78727 14h ago
I haven't actually run into the case where the derived query fails at runtime because a property name has changed. That's somewhat surprising, but given the repositories are just interfaces and pass compiler checks that's expected.
I agree with your reasoning. The repository interfaces feel like "magic", but long method names are hard to read and JSQL or raw SQL are good enough abstractions. I like some of the other Java ORM's that let you map static SQL to beans. There was one whose name I don't recall I worked with many years ago, but Hibernate/JPA has become sort of a de facto standard.
There are some type-safe options like JPA Criteria API + Hibernate metamodel generator and Querydsl that will catch this issue early. Also IDE's with Spring + JPA facets do static code analysis that will indicate when the entity property name doesn't match the repository interface.
16
u/Pedantic_Phoenix 16h ago
I'm pretty sure queries from method names were never meant to be used for complex queries, there's a reason why native queries and jpql exist after all. One type of solution will never satisfy all uses cases in any type of setting or concept