2

I searched around but I only get people asking the opposite of my question. So let's say we have:

@Entity
class Book {
  ...
  @ManyToOne(fetch = FetchType.LAZY)
  private Author author;
}

Is there a (preferably global) property/way in JPA/Hibernate to prevent from ever lazily loading the author (or any entity)?

Don't get me wrong, I don't want to use EAGER fetch. I want to prevent juniors from ever accidentally calling book.getAuthor().getName() and making another DB call. A lot of people are looking to fix their LazyInitializationException, but I basically want to force such an exception to be thrown even if there is an active session (which when using @Transactional is quite an easy mistake to make). However I also still want Author to be fetched if you properly use "JOIN FETCH Author" in your JPQL query.

My particular use case is with Spring and GraphQL. @Transactional quite easily hides when a session is open and avoids the LazyInitializationException. And with GraphQL you can specify which fields to get so I don't want unnecessarily joins when such fields aren't requested (here we use a Field Resolver with a DataLoader).

  • In theory, using `FetchType.LAZY` should already make the fetch lazy. But in practice, using `FetchType.LAZY` is just a suggestion, and JPA may still eagerly load the `Author` reference. – Tim Biegeleisen Dec 13 '21 at 02:42
  • Just tell your team to not specify anything and let Hibernate choose the best mode. Indeed, by default, the JPA \@ManyToOne and \@OneToOne annotations are fetched EAGERly, while the \@OneToMany and \@ManyToMany relationships are considered LAZY. This is the default strategy – TacheDeChoco Dec 13 '21 at 13:26
  • See this if it helps with your problem https://stackoverflow.com/a/31715790/1460591 – Youans Dec 13 '21 at 13:28
  • You can't avoid them to fetch new DB call. Let's suppose you user `LAZY` in all kind of relationships... if junior developers try to access to some related object outside the hibernate session (that is outside JPA transaction) they will get an error but... if they try to access inside the hibernate session (o JPA transaction) hibernate will try to "fill" the proxied objects by doing a new call. IMHO the best way is to use the `LAZY` fetching where needed (maybe the default settings are enough) and check the code quality to realize if there is some bad usage of it – Angelo Immediata Dec 13 '21 at 13:30
  • @TacheDeChoco But I don't want ManyToOne relationships to be fetched eagerly and unnecessarily make additional joins even when they're not needed (for example when using GraphQL you can specify which fields to get). And someone still might do something like author.getBooks() with OneToMany relationships and cause the N+1 problem. I want to prevent and guard against all such problems. – DarthBatman123 Dec 13 '21 at 13:35

1 Answers1

0

Would a sufficient workaround be to instead use a projection (https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#projections) of the Book entity without the reference to the author? And by working with different projections guarantee that related entities are not unintentionally loaded?

Johan Nordlinder
  • 1,672
  • 1
  • 13
  • 17