简体   繁体   中英

Spring Boot, many to one relationship fetch LAZY or EAGER

Two entities with a bidirectional one to many relationship.

Entity A points to a list of entity B's which will be several at most. Entity B has a back reference to an A.

When displayed as JSON, I was expecting to see A with a number of B's or B with its corresponding A. But that seems to depend on the fetch strategy in the @OneToMany or @ManyToOne annotation.

Most things I have read says @ManyToOne should be LAZY, and the @OneToMany should be EAGER. And that approach will work when listing entity A; each A and it's associated B's are shown in JSON.

But when listing B's, I get an error

Type definition error: [simple type, class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.hibernate.proxy.pojo.bytebuddy.ByteBuddyInterceptor and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS

Changing the LAZY to EAGER fixes the problem. But, with LAZY, I would have expected it to at least bring up the B records. The error is surprising.

I will just add that both entity definitions use JsonIdentityInfo (added to prevent infinite recursion) which uses a SimpleObjectIdResolver.

So, in summary, I am confused. I can make it "work" but not really sure why.

Most things I have read says @ManyToOne should be LAZY, and the @OneToMany should be EAGER. And that approach will work when listing entity A; each A and it's associated B's are shown in JSON.

That is not what should be done, but the default. This can be seen in the @ManyToOne - and @OneToMany -documentation. What should be done varyies from use-case to use-case.


To the exception: If a relationship is defined with lazy loading, a proxy-object is inserted, and the real entity is fetched from database when needed. Jackson tries to serialize the proxy and fails. This hints at a deeper, architectual design flaw: why are you trying to serialize a database entity? There should be at least one layer between the database and a serialization process (eg through a DTO transformation).

Even if serialization would work as expected (ie the missing entity is fetched), it is most probable that the transaction, with which the entity was loaded, is already closed and the process will result in a LazyInitializationException . If you know up front that you always need the relation to be fetched, make it eagerly fetched. If you only need to fetch relations in certain cases, encode the fetching in JPQL, a CriteriaQuery of, if necessary, in a native query. Fetching a lazy loaded @OneToMany relationship will result in the N+1 problem , which should be avoided at all costs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM