Ce n'est pas si facile car Hibernate/JPA essaie de garantir que le modèle d'entité est synchronisé avec l'état de la base de données. Vous voulez apparemment une projection qui ne devrait probablement pas être synchronisée avec la base de données. Si vous devez vraiment le faire, vous pouvez utiliser la requête suivante, mais sachez que cela peut entraîner la suppression d'éléments de service dans la collection qui ne correspondent pas aux critères :
@Query(value = "SELECT DISTINCT req FROM request req JOIN FETCH req.services srvs WHERE (srvs.status = :serviceStatus)")
List<Request> getAll(@Param("serviceStatus") String serviceStatus);
Ceci est généralement géré en introduisant des DTO et je pense que c'est un cas d'utilisation parfait pour Vues d'entité Blaze-Persistence .
J'ai créé la bibliothèque pour permettre une cartographie facile entre les modèles JPA et l'interface personnalisée ou les modèles définis par classe abstraite, quelque chose comme Spring Data Projections sur les stéroïdes. L'idée est de définir votre structure cible (modèle de domaine) comme vous le souhaitez et de mapper les attributs (getters) via des expressions JPQL au modèle d'entité.
Un modèle DTO pour votre cas d'utilisation pourrait ressembler à ce qui suit avec Blaze-Persistence Entity-Views :
@EntityView(Request.class)
public interface RequestDto {
@IdMapping
Integer getId();
String getStatus();
@Mapping("services[status = :serviceStatus]")
Set<ServiceDto> getServices();
@EntityView(Service.class)
interface ServiceDto {
@IdMapping
Integer getId();
Integer getRequestId();
String getStatus();
}
}
L'interrogation consiste à appliquer la vue d'entité à une requête, la plus simple étant simplement une requête par identifiant.
RequestDto a = entityViewManager.find(entityManager, RequestDto.class, id);
L'intégration de Spring Data vous permet de l'utiliser presque comme Spring Data Projections :https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features
List<RequestDto> findAll(@OptionalParam("serviceStatus") String serviceStatus);
La meilleure partie est qu'il ne récupérera que l'état réellement nécessaire !