Hibernate CriteriaBuilder 连接多个表
Hibernate CriteriaBuilder to join multiple tables
我正在尝试使用 hibernate criteriabuilder 连接 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 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 for that (or consult 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>
我正在尝试使用 hibernate criteriabuilder 连接 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 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 for that (or consult 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>