That's no easy task. If you rely on lazy loading outside of the data layer, you will have to rework the data layer to fit all those needs. The easiest way is to use @EntityGraph
on your repository methods to do the fetching of associations. Sometimes you will have to duplicate methods for different use cases to apply different @EntityGraph
annotations. There are still some issues you can run into in such a design, but this should get you pretty far already.
IMO the best solution is to use DTOs as this will improve the performance when done right and eliminates all lazy loading issues. The "problem" is though, that this approach might require quite a few changes in your application.
Either way, I would recommend you take a look at what Blaze-Persistence Entity Views has to offer as a way to implement a DTO approach.
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.
A 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();
}
}
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
UserDto findOne(Long id);
Using Entity-Views will improve performance immediately as it will only fetch the state that is necessary.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…