2017-04-14 1 views
0

Il existe souvent une question métier pour afficher toutes les catégories et la fréquence d'utilisation de ces catégories.Méthode privilégiée pour mapper un ensemble de résultats avec l'entité et le nombre à l'aide des données de base

Cette question est facile de répondre à une requête:

SELECT c.*, count(*) FROM category_assignment ca LEFT JOIN category c on ca.c_id = c.id group by c.id 

Ce que je vous demande est votre suggérât pour cartographier l'ensemble des résultats selon les critères suivants:

@Entity 
public class CategoryAssignment { 
    @Id 
    int id; 

    @ManyToOne(fetch = FetchType.EAGER) 
    private Category category; 

    @ManyToOne(fetch = FetchType.EAGER) 
    private Car car; 
} 


@Entity 
public class Category { 
    @Id 
    String id; 
    TypeEnum type; 
    ... 
} 

@Entity 
public class Car { 
    @Id 
    int id; 
    String name; 
    ... 
} 

De mon point de vue le meilleur résultat de la cartographie serait d'obtenir un objet personnalisé qui contient la catégorie en tant qu'entité et le nombre de comptage en tant que variable supplémentaire dès la fin de l'appel du référentiel:

MappingResult result = repository.getCategoriesAndTheirCountOfType(TypeEnum type); 

public class MappingResult { 
    Category category; 
    BigInteger count; 
} 

Seule la façon dont j'ai pu y parvenir jusqu'à maintenant consistait à mapper le jeu de résultats manuellement. Mais j'espère qu'il y a des façons plus faciles de la cartographier.

Répondre

0

Vous pouvez utiliser Projections pour l'obtenir:

public interface CategoryAndCount { 
    Category getCategory(); 
    Long getUsageCount(); 
} 

public interface CategoryAssignmentRepository extends CrudRepository<CategoryAssignment, Integer> { 

    @Query("select c as category, count(*) as usageCount from CategoryAssignment ca join ca.category c where c.type = ?1 group by c") 
    CategoryAndCount getCategoriesAndTheirCountOfType(TypeEnum type); 
} 

Ne pas oublier d'ajouter alias au champ dans la requête (c comme catégorie , count (*) comme UsageCount).

More info

+0

Merci. Je connaissais Projections mais je n'arrivais pas à le coder correctement. Votre réponse me laisse dans la bonne direction. Ma plus grosse erreur a été de définir @Query (nativeQuery = true) qui exécute SQL. Ce dont j'avais besoin était Jpql et donc pas besoin du drapeau nativeQuery. –

0

Vous pouvez l'avoir comme propriété d'un Catgeory en suivant l'une des 2 approches. L'avantage est que la propriété est toujours disponible et que vous n'avez pas besoin d'appeler une requête spécifique.

  1. Création d'une vue de base de données, par exemple category_summary_data puis cette commande à une catégorie en utilisant soit une table secondaire ou comme @OneToOne

-

@Entity 
@Table(name = "categories") 
@SecondaryTable(name = "category_summary_data", pkJoinColumns = {...}) 
public class Category { 
    @Id 
    String id; 
    TypeEnum type; 

    @Column(name = "usage_count", table = "category_summary_data", insertable = false, updateable = false) 
    // do not use int https://stackoverflow.com/questions/43407889/prefered-way-to-map-a-result-set-with-entity-and-count-using-spring-data/43411008#43411008 
    Integer usageCount; 
} 
  1. Vous pouvez également utiliser une extension de fournisseur. Hibernate offre l'annotation @Formula que vous pouvez utiliser pour définir les valeurs calculées.

-

@Entity 
@Table(name = "categories") 
public class Category { 
    @Id 
    String id; 
    TypeEnum type; 

    @Formula("some sql to count the records") 
    int usageCount; 
} 
+0

thx pour la réponse - je n'ai jamais pensé à le faire de cette façon. Pour mon cas d'utilisation, Projections est la meilleure solution. Mais je garderai votre approche dans mon esprit pour une utilisation future. –