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