Spring Data JPA + Bytecode Enhancement

791 Views Asked by At

Is it possible to load @*ToOne attributes eagerly using JPA interface(Entity Graphs) which are set lazy using @LazyToOne , @LazyGroup in the parent entity class and enabled bytecode enhancement ? I am trying to load such attributes eagerly using entity graph but it is firing another query for such @*ToOne attributes when an parent entity is queried.

Trying to have another way to override static fetch type in entity classes including @LazyToOne which was added with bytecode enhancement.

Using Spring 5.1.3 , Spring JPA 2.2 , Hibernate 5.4.19

Update : Data JPA is working as expected and i could see joins for the attributes which i am trying to fetch eagerly but those lazy attributes are not being initialised with the join query response and hibernate causing each query on referencing attributes which were annotated with @LazyToOneOption.NO_PROXY and was already fetched eagerly using entity graph in my repository.

How can i avoid this second select which is not even required since i got the that data eagerly from entity graph in JPA respository ??

Any help would be highly appreciated.

1

There are 1 best solutions below

1
On

Entity Graphs just like Hibernate fetch profiles apply regardless of what annotations you have on the association. If it does not, maybe there is a bug in Spring Data or maybe even Hibernate. It's probably best if you create a new JIRA issue with a test case reproducing the problem.

Having said that, I think this is the perfect use case for Blaze-Persistence Entity Views.

I created the library to allow easy mapping between JPA models and custom interface or abstract class defined models, something like Spring Data Projections on steroids. The idea is that you define your target structure(domain model) the way you like and map attributes(getters) via JPQL expressions to the entity model.

An example DTO model could look like the following with Blaze-Persistence Entity-Views:

@EntityView(User.class)
public interface UserDto {
    @IdMapping
    Long getId();
    String getName();
    Set<RoleDto> getRoles();

    @EntityView(Role.class)
    interface RoleDto {
        @IdMapping
        Long getId();
        String getName();
    }

    // Other mappings
}

Querying is a matter of applying the entity view to a query, the simplest being just a query by id.

UserDto a = entityViewManager.find(entityManager, UserDto.class, id);

The Spring Data integration allows you to use it almost like Spring Data Projections: https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features