向 JPA CriteriaQuery 添加连接

Posted

技术标签:

【中文标题】向 JPA CriteriaQuery 添加连接【英文标题】:Adding a join to a JPA CriteriaQuery 【发布时间】:2021-11-11 08:16:43 【问题描述】:

我的 FlowStep 对象上有一个 CriteriaQuery。

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<FlowStep> cbQuery = cb.createQuery(FlowStep.class);
Root<FlowStep> flowStep = cbQuery.from(FlowStep.class);


List<Predicate> predicates = new ArrayList<>();

然后我根据要过滤的内容添加许多谓词。

// add all the conditions to query
cbQuery.select(flowStep).where(predicates.toArray(new Predicate[0]));

我什至添加了排序的东西。

cbQuery.orderBy(orders);

Query query = em.createQuery(cbQuery);

List<FlowStep> resultList = query.getResultList();

但我需要像这样添加一个连接:

select * from flowstep fs join flowinstance fi on fi.id = fs.flowinstanceid and fi.domainid = 'Test'

所以我只想返回匹配条件 AND 的流程步骤在测试域中,域信息在表 flowinstance 中。 如何将联接添加到 CriteriaQuery?

我看到了类似的东西

Join<FlowStep, UUID> flowStepFlowInstanceJoin = flowStep.join(FlowInstance_.id);

但是我需要在域上添加条件等于一个值。

是否可以在 JPQL 条件查询中使用上述连接?

最初的答案是在谓词列表之前添加这个:

Join<FlowStep, FlowInstance> flowStepFlowInstanceJoin = flowStep.join("id", JoinType.LEFT);
flowStepFlowInstanceJoin.on(cb.equal(flowStepFlowInstanceJoin.get("domainid"), domain));

FlowStep 有一个 flowinstanceid 列和字段,flowinstance 有一个 id 字段。 这可以编译但不起作用。 我收到错误“无法加入基本类型的属性”。 那么FlowStep和FlowInstance之间需要存在一对多的关系吗? FlowInstance 有很多流程步骤,所以可能

@Column(name = flowinstanceid)
private UUID flowInstanceId;

FlowStep类中需要改成JoinColumn吗?并添加 OneToMany 或 ManyToOne 关系以使上述 JOIN 成为可能?

【问题讨论】:

【参考方案1】:

CriteriaBuilder join two tables with a custom condition 和 JPA many-to-one relation - need to save only Id 提出了解决方案。

在 FlowStep 类中,我们需要添加 FlowInstance 对象和一个 ManyToOne 注解:

@JoinColumn(name = FLOW_INSTANCE_ID, insertable = false, updatable = false)
@ManyToOne(targetEntity = FlowInstance.class, fetch = FetchType.EAGER)
@JsonIgnore
private FlowInstance flowInstance;

请注意,该类已经有一个用于 UUID 类型的流实例 id 的字段,但对于 ManyToOne 关系,似乎需要一个 FlowInstance 类的字段。

那么在构建JPA查询时:

Join<FlowStep, FlowInstance> flowStepFlowInstanceJoin = flowStep.join("flowInstance", JoinType.INNER); 
flowStepFlowInstanceJoin.on(cb.equal(flowStepFlowInstanceJoin.get("domainId"), domain));

这低于

Root<FlowStep> flowStep = cbQuery.from(FlowStep.class);

线。 这使它工作。 连接的类型为 INNER 非常重要,这样它只返回具有所需域的步骤。 LEFT 将返回具有非所需域的步骤,而 RIGHT 将返回与具有所需域的步骤一样多的空行。

【讨论】:

以上是关于向 JPA CriteriaQuery 添加连接的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JPA 调整为 Criteriaquery

JPA 2 CriteriaQuery,使用限制

日期之间的 JPA 2.1 CriteriaQuery

JPA CriteriaQuery - 不区分重音

CriteriaQuery JPA 2 问题与结果

JPA CriteriaQuery 多对多谓词