Hibernate CriteriaBuilder 加入多个表

Posted

技术标签:

【中文标题】Hibernate CriteriaBuilder 加入多个表【英文标题】:Hibernate CriteriaBuilder to join multiple tables 【发布时间】:2017-06-18 09:21:38 【问题描述】:

我正在尝试使用休眠条件生成器加入 4 个表.. 下面分别是表格.. `

@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


在这 4 个表中,我想为 mysql 执行以下 sql 脚本:

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'

那么,如何使用 Hibernate CriteriaBuilder 来实现这一点?请帮忙... 提前谢谢.......

【问题讨论】:

第一个问题是,你真的需要在这里使用条件吗..这将是一个动态查询..还是只是参数会改变? 是的,我必须在这里使用 CriteriaBuilder.... 而且这里的参数也会改变 【参考方案1】:
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(buildDetailsTable.get(BuildDetails_.buildNumber), "1.0.0.1"));
predicates.add(cb.equal(buildDetailsTable.get(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();

我假设您为自己的类构建了 JPA 元模型。如果您没有元模型或者您只是不想使用它,只需将BuildDetails_.buildNumber 替换为列的实际名称String,例如"buildNumber".

请注意,我无法测试答案(也是在没有编辑器支持的情况下编写的),但它至少应该包含构建查询所需的所有内容。

如何构建您的元模型?看看hibernate tooling (或咨询How to generate JPA 2.0 metamodel? 了解其他替代方案)。如果您使用的是 maven,那么只需将 hibernate-jpamodelgen-dependency 添加到您的构建类路径中即可。由于我现在没有任何此类项目可用,因此我对以下内容不太确定(因此请谨慎对待)。只需添加以下作为依赖项就足够了:

<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>

【讨论】:

作为 JPA 新手,如果这个答案显示了如何构建或获取 JPA 元模型,那将真的很有帮助。另外,当您写“列的实际名称”时,您是指实体类的字段名称(而不是数据库列名称)吗? 添加了关于如何生成该元模型的简短说明...请注意,我现在没有任何可用的 JPA 项目,所以我不能确定...但它是绝对容易生成...关于列的名称与类的字段名称:我认为是后者...您可能需要查找 Javadoc (Path.get(String))... 我发现了一个可能对其他人有帮助的错字。 cb.equal(BuildDetails_.buildNumber, "1.0.0.1") cb.equal(BuildDetails_.projectName, "Tera") 不正确。应该是 cb.equal(buildDetailsTable.get(BuildDetails_.buildNumber, "1.0.0.1")) cb.equal(buildDetailsTable.get(BuildDetails_.projectName, "Tera")) @MichaelRountree 听起来很合理.. 将更新答案以反映它.. 感谢您的指出!

以上是关于Hibernate CriteriaBuilder 加入多个表的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate CriteriaBuilder 加入多个表

Hibernate CriteriaBuilder - 如何匹配具有相同字段的所有元素,其中 id 相同

将String传递给String 对于使用Hibernate的CriteriaBuilder.equal方法

Hibernate Criteriabuilder Query with part of a complex id

JPA CriteriaBuilder in条件构建问题

如何告诉 JPA CriteriaBuilder 按返回的唯一数据列排序?