2017-02-14 14 views
10

Tôi có truy vấn SQL mẹ đẻ sau mà tôi đang cố gắng để chuyển đổi tiêu chí JPA:chuyển đổi của SQL Left Outer Join Query để Tiêu chuẩn 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) 

(Lưu ý rằng (+) là tương đương với một trái bên ngoài tham gia trong trường hợp này. Có, tôi biết nó biểu thị bảng TÙY CHỌN, v.v ...).

Đây là nỗ lực của tôi vào mã:

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(); 

Vấn đề này dường như là tôi đang cố gắng để tham gia vào một cột chuỗi, assigedDepartment, đến một lĩnh vực duy nhất của một ID composite. Điều này là hoàn toàn hợp pháp trong SQL, nhưng không dễ dàng như vậy trong mã.

Một tùy chọn là chuyển đổi thành một số truy vấn phụ, điều này dường như sẽ giết hoàn toàn điểm liên kết bên ngoài bên trái.

Có ai có thể chỉ ra những gì tôi đang làm sai?

Jason

+0

Không có thời gian để viết một câu trả lời nhưng " chọn entity1 từ entity1 left join entity1.field2 where ... ". Nếu bạn muốn tham gia bên trái để được háo hức lấy bạn cần phải có "trái tham gia lấy". –

+0

Thuộc tính JoinType chỉ có ba giá trị có thể: INNER, LEFT và RIGHT. Có vẻ như không phải là một tùy chọn để tìm nạp tham gia bên trái. Ngoài ra, có sự cố với dòng join(). Mặc dù join() trả về một SingularAttribute <>, nhưng tôi không thể chuỗi các lệnh như thế. – Jason

+1

Trong truy vấn JPA Criteria bạn đang tham chiếu đến một bảng 'DepartmentCompositeId' không có trong truy vấn SQL. Vui lòng hoàn thành thông tin bằng cách thêm các phần có liên quan của định nghĩa của mỗi thực thể – perissf

Trả lời

2

Bạn nên đăng các thực thể của mình để câu trả lời có thể cụ thể hơn.

Tuy nhiên, tôi sẽ thử.

Nếu tôi đúng, bạn có thể viết lại truy vấn:

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) 

Vì vậy, trong thời gian ngắn, bạn phải di chuyển JoinType.LEFT-assignedDepartment tham gia:

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(); 
Các vấn đề liên quan