web-dev-qa-db-fra.com

Hibernate CriteriaBuilder pour joindre plusieurs tables

J'essaie de joindre 4 tables en utilisant le critère de mise en veille prolongée ..
Voici les tableaux respectivement .. `

@Entity
public class BuildDetails {
    @Id
    private long id;
    @Column
    private String buildNumber; 
    @Column
    private String buildDuration;
    @Column
    private String projectName;

}   

@Entity
public class CodeQualityDetails{
    @Id
    private long id;
    @Column
    private String codeHealth;
    @ManyToOne
    private BuildDetails build; //columnName=buildNum
}

@Entity
public class DeploymentDetails{
    @Id
    private Long id;
    @Column
    private String deployedEnv;
    @ManyToOne
    private BuildDetails build; //columnName=buildNum
}

@Entity
public class TestDetails{
    @Id
    private Long id;
    @Column
    private String testStatus;
    @ManyToOne
    private BuildDetails build; //columnName=buildNum
}


Dans ces 4 tableaux, je voudrais exécuter le script sql ci-dessous pour MySQL:

SELECT b.buildNumber, b.buildDuration,
       c.codeHealth, d.deployedEnv, t.testStatus
FROM BuildDetails b
INNER JOIN CodeQualityDetails c ON b.buildNumber=c.buildNum
INNER JOIN DeploymentDetails d ON b.buildNumber=d.buildNum
INNER JOIN TestDetails t ON b.buildNumber=t.buildNum
WHERE b.buildNumber='1.0.0.1' AND
      b.projectName='Tera'

Alors, comment puis-je y parvenir en utilisant Hibernate CriteriaBuilder? Veuillez aider ...

Merci d'avance.......

14
ktgirish
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery query = cb.createQuery(/* Your combined target type, e.g. MyQueriedBuildDetails.class, containing buildNumber, duration, code health, etc.*/);

Root<BuildDetails> buildDetailsTable = query.from(BuildDetails.class);
Join<BuildDetails, CopyQualityDetails> qualityJoin = buildDetailsTable.join(CopyQualityDetails_.build, JoinType.INNER);
Join<BuildDetails, DeploymentDetails> deploymentJoin = buildDetailsTable.join(DeploymentDetails_.build, JoinType.INNER);
Join<BuildDetails, TestDetails> testJoin = buildDetailsTable.join(TestDetails_.build, JoinType.INNER);

List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(BuildDetails_.buildNumber, "1.0.0.1"));
predicates.add(cb.equal(BuildDetails_.projectName, "Tera"));

query.multiselect(buildDetails.get(BuildDetails_.buildNumber),
                  buildDetails.get(BuildDetails_.buildDuration),
                  qualityJoin.get(CodeQualityDetails_.codeHealth),
                  deploymentJoin.get(DeploymentDetails_.deployedEnv),
                  testJoin.get(TestDetails_.testStatus));
query.where(predicates.stream().toArray(Predicate[]::new));

TypedQuery<MyQueriedBuildDetails> typedQuery = entityManager.createQuery(query);

List<MyQueriedBuildDetails> resultList = typedQuery.getResultList();

Je suppose que vous avez créé le métamodèle JPA pour vos cours. Si vous n'avez pas le métamodèle ou si vous ne voulez tout simplement pas l'utiliser, remplacez simplement BuildDetails_.buildNumber et le reste avec les noms réels de la colonne comme String, par exemple "buildNumber".

Notez que je n'ai pas pu tester la réponse (je l'écrivais également sans l'aide de l'éditeur), mais elle devrait au moins contenir tout ce que vous devez savoir pour créer la requête.

Comment construire votre métamodèle? Jetez un œil à mise en veille prolongée pour cela (ou consultez Comment générer le métamodèle JPA 2.0? pour d'autres alternatives). Si vous utilisez maven, cela peut être aussi simple que d'ajouter simplement le hibernate-jpamodelgen- dépendance à votre chemin de classe de génération. Comme je n'ai pas un tel projet maintenant disponible, je ne suis pas sûr de ce qui suit (alors prenez-le avec un grain de sel). Il peut suffire d'ajouter simplement ce qui suit en tant que dépendance:

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-jpamodelgen</artifactId>
  <version>5.3.7.Final</version>
  <scope>provided</scope> <!-- this might ensure that you do not package it, but that it is otherwise available; untested now, but I think I used it that way in the past -->
</dependency>
13
Roland