gpt4 book ai didi

java - 将 SQL 左外连接查询转换为 JPA 条件

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:01:34 25 4
gpt4 key购买 nike

我尝试将以下 native SQL 查询转换为 JPA 条件:

select et.* from t_empl_tx et, t_dept d 
where et.assigned_dept = d.dept (+)
and et.employee_id = :employee_id
and (et.start_date >= d.dept_est_date and
et.start_date <= d.dept_close_date or
et.start_date is null or
d.dept is null)

(请注意,在这种情况下,(+) 大致等同于左外部联接。是的,我知道它表示可选表等)。

这是我对代码的尝试:

EntityManager entityManager = getEntityManager();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<EmployeeTransaction> criteriaQuery = criteriaBuilder.createQuery(EmployeeTransaction.class);
Root<EmployeeTransaction> root = criteriaQuery.from(EmployeeTransaction.class);

// this line bombs!
Join<EmployeeTransaction, Department> join =
root.join(EmployeeTransaction_.assignedDepartment).join(Department_.id).join(DepartmentCompositeId_.department, JoinType.LEFT);

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

predicates.add(criteriaBuilder.equal(root.get(EmployeeTransaction_.id).get(EmployeeTransactionCompositeId_.employeeId), employeeId));
predicates.add(criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.greaterThanOrEqualTo(root.<Date>get(EmployeeTransaction_.requestedStartDate), join.get(Department_.id).<Date>get(DepartmentCompositeId_.departmentCreationDate)),
criteriaBuilder.lessThanOrEqualTo(root.<Date>get(EmployeeTransaction_.requestedStartDate), join.<Date>get(Department_.departmentCloseDate))
),
criteriaBuilder.isNull(root.get(EmployeeTransaction_.requestedStartDate)),
criteriaBuilder.isNull(join.get(Department_.id).get(DepartmentCompositeId_.departmentCreationDate))
));

criteriaQuery.select(root).where(predicates.toArray(new Predicate[]{}));

TypedQuery<EmployeeTransaction> query = entityManager.createQuery(criteriaQuery);
List<EmployeeTransaction> result = query.getResultList();

这个问题似乎是因为我正在尝试将字符串列 assigedDepartment 连接到复合 ID 的单个字段。这在 SQL 中是完全合法的,但在代码中并不那么容易。

一个选项是转换为多个子查询,这似乎完全扼杀了左外连接的意义。

谁能指出我做错了什么?

杰森

最佳答案

您应该发布您的实体,以便答案更加具体。

但是,我会试一试。

如果我是对的,你可以重写查询:

select et.* 
from t_empl_tx et
left join t_dept d on et.assigned_dept = d.dept
where
et.employee_id = :employee_id
and (
et.start_date >= d.dept_est_date
and et.start_date <= d.dept_close_date
or et.start_date is null
or d.dept is null)

因此,很快,您必须将 JoinType.LEFT 移动到 assignedDepartment 加入:

EntityManager entityManager = getEntityManager();
CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
CriteriaQuery<EmployeeTransaction> criteriaQuery = criteriaBuilder.createQuery(EmployeeTransaction.class);

Root<EmployeeTransaction> root = criteriaQuery.from(EmployeeTransaction.class);
Join<EmployeeTransaction, Department> department = root.join(EmployeeTransaction_.assignedDepartment, JoinType.LEFT);
Path<Date> employeeTransactionRequestedStartDate = root.get(EmployeeTransaction_.requestedStartDate);
Path<DepartmentCompositeId> departmentId = department.get(Department_.id);
Path<Date> departmentCreationDate = departmentId.get(DepartmentCompositeId_.departmentCreationDate)
Path<Date> departmentCloseDate = departmentId.get(DepartmentCompositeId_.departmentCloseDate)

criteriaQuery.select(root).where(
criteriaBuilder.equal(root.get(EmployeeTransaction_.id).get(EmployeeTransactionCompositeId_.employeeId), employeeId),
criteriaBuilder.or(
criteriaBuilder.and(
criteriaBuilder.greaterThanOrEqualTo(employeeTransactionRequestedStartDate, departmentCreationDate)),
criteriaBuilder.lessThanOrEqualTo(employeeTransactionRequestedStartDate, departmentCloseDate)
),
criteriaBuilder.isNull(employeeTransactionRequestedStartDate),
criteriaBuilder.isNull(departmentCreationDate)
)
);

TypedQuery<EmployeeTransaction> query = entityManager.createQuery(criteriaQuery);
List<EmployeeTransaction> result = query.getResultList();

关于java - 将 SQL 左外连接查询转换为 JPA 条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42226363/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com