【问题标题】:Crieria API query using criteriabuilder.construct with a non existing relationship使用不存在关系的 criteriabuilder.construct 进行条件 API 查询
【发布时间】:2020-07-03 01:04:48
【问题描述】:

鉴于这个非常简单的 DTO:

@Entity
public class Employee implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

private String name;

@OneToOne
private Employee boss;

}

我想进行一个查询,收集所有员工姓名和他们老板的 ID,放入一个干净整洁的 POJO:

public class EmployeeInfo {

private String name;
private Long bossId;

public EmployeeInfo(String name, Long bossId) {
    this.name = name;
    this.bossId = bossId;
}

}

这个查询应该有用:

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<EmployeeInfo> query = cb.createQuery(EmployeeInfo.class);
Root<Employee> root = query.from(Employee.class);
query.select(
        cb.construct(EmployeeInfo.class,
                root.get("name").as(String.class),
                root.get("boss").get("id").as(Long.class)));
result = em.createQuery(query).getResultList();

当员工列中存在 bossId 时,这工作得很好。但是当没有设置老板ID时,该记录将被完全忽略。那么对于构造/多选,我如何将这个不存在的老板关系视为 null 或 0?

在纯 SQL 中很容易:

SELECT name, COALESCE(boss_id, 0) FROM EMPLOYEE;

但看在上帝的份上,我不能让标准 api 做到这一点。

cb.construct(EmployeeInfo.class,
        root.get("name").as(String.class),
        cb.coalesce(root.get("boss").get("id").as(Long.class), 0L)));

【问题讨论】:

  • 如果尝试root.join("boss", JoinType.LEFT) 而不是root.get("boss") 会怎样。它应该在没有coalesce 的情况下工作
  • 就是这样。我想感谢您的回答,请发布一个专门的答案。谢谢

标签: jpa eclipselink jpa-2.0 criteria-api


【解决方案1】:

问题是root.get("boss") 生成像from Employee employee, Employee boss where employee.boss.id=boss.id 这样的交叉连接查询。因此,employee.boss.id is null 的记录将被忽略。

要解决问题,您应该使用root.join("boss", JoinType.LEFT) 而不是root.get("boss")

【讨论】:

    猜你喜欢
    • 2012-07-05
    • 1970-01-01
    • 2012-11-25
    • 2015-08-14
    • 2021-08-30
    • 2011-02-22
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    相关资源
    最近更新 更多