0

I have two @OneToOne entities:

...
public class A {
  
   ...
   
   @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "b_id", nullable = false)
   private B b; 

   ...
}

...
public class B {

...

@OneToOne(fetch = FetchType.LAZY, mappedBy = "b", cascade = CascadeType.ALL, orphanRemoval = true)
private A a;

...
}

and I'm using spring data JPA JpaRepository<T, ID> to fetch all entities (findAll() method).

Is it possible to fetch all B entities with lazily initialized A property (to not fetch A property whenever I fetch all B entities? If not, is it possible to avoid N+1 select in this case?

Edit: My question is different from How can I make a JPA OneToOne relation lazy How can I make a JPA OneToOne relation lazy because mine is other way around, I want to fetch parent entities and/or to avoid N+1 select while fetching it.

pera.coyote
  • 39
  • 1
  • 7
  • Does this answer your question? [How can I make a JPA OneToOne relation lazy](https://stackoverflow.com/questions/1444227/how-can-i-make-a-jpa-onetoone-relation-lazy) – SternK Jul 07 '20 at 12:11
  • Nope, my problem is other way around. How to fetch parent entities, with "mappedBy". – pera.coyote Jul 07 '20 at 12:54

2 Answers2

0

Edit: My question is different from How can I make a JPA OneToOne relation lazy How can I make a JPA OneToOne relation lazy because mine is other way around, I want to fetch parent entities and/or to avoid N+1 select while fetching it.

The only way you can do it is to change your @OneToOne association to uni-directional.

But you are using a bi-directional @OneToOne association, so it's not possible***. The parent-association will always do a FetchType.EAGER. The reason being that

For every managed entity, the "Persistence Context" needs both the entity type and the identifier, so the child identifier must be known when loading the parent entity, and the only way to find the associated "class A" primary key is to execute a second select.

***: If you want to avoid the second select, Bytecode enhancement is the only viable workaround. However, it only works if the parent side is annotated with @LazyToOne(LazyToOneOption.NO_PROXY) and the child side is not using @MapsId.

BONUS:
The most efficient way to map a @OneToOne is described by the great Vlad here. In short, use @MapsId.

jumping_monkey
  • 2,284
  • 14
  • 25
0

Is it possible to fetch all B entities with lazily initialized A property (to not fetch A property whenever I fetch all B entities? If not, is it possible to avoid N+1 select in this case?

Maybe it's possible when you use property access rather than field access. With field access the one-to-one association has to initialized eagerly because it can't use a proxy. It can't because the field would have to be null if the object does not exist. With property access this can be deferred to the first call to a getter, but that might be a problem as well.

Maybe you can use a fetch join to avoid the N + 1 problem or use a DTO?

Christian Beikov
  • 6,925
  • 1
  • 26
  • 48