2012-03-29 50 views
6

Bất kỳ ai cũng có thể giúp tôi nhận được truy vấn tiêu chí JPA cho truy vấn JPA được đề cập bên dưới.Cách viết truy vấn này bằng truy vấn Tiêu chí JPA?

SELECT p,l FROM Person p 
LEFT JOIN Language l ON (p.language = l.language and l.locale like :locale) 
AND p.name like :name 
AND p.time BETWEEN :startDate 
AND :endDate order by name asc 
+0

Bạn có thể hiển thị các triển khai của mình cho Người và Ngôn ngữ không? –

Trả lời

10

Giả sử rằng Người có liên quan đến ngôn ngữ ở đây là những gì bạn sẽ làm gì trong Hibernate cũ:

Criteria criteria = entityManager.createCriteria(Person.class); 
Criteria languageCriteria = criteria.createCriteria("language"); 

languageCriteria.add(Restrictions.like("locale", locale)); 

criteria.add(Restrictions.like("name", name)); 
criteria.add(Restrictions.between("time", startDate, endDate)); 

criteria.addOrder(Order.asc("name")); 

và thử đầu tiên của tôi tại JPA 2.0:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate conjunction = builder.conjunction(); 

criteria.where(builder.and(
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

Xin vui lòng cho tôi biết nếu điều đó phù hợp với bạn.

Chỉnh sửa: Truy vấn được cập nhật để chỉ sử dụng một cuộc gọi where.

+4

Hạn chế không phải là một phần của thông số kỹ thuật JPA, đó là một tính năng Hibernate – perissf

+0

Bạn là chính xác, tôi cần dịch sang JPA 2 –

+0

Xin cảm ơn trước hết, tôi nên đặt câu hỏi này lên. Có ** không có mối quan hệ ** b/w đối tượng và ngôn ngữ của thực thể. Cả hai người và ngôn ngữ có một cột chung (ngôn ngữ (varchar)) mà tôi đang tham gia. những gì gây ra vấn đề cho tôi là, tôi cần phải thực hiện một ** LEFT OUTER JOIN ** để nếu không có dữ liệu ngôn ngữ có sẵn cho người đó, tôi vẫn có thể lấy dữ liệu người với đối tượng ngôn ngữ là null . – user1300877

6

Mặc dù câu trả lời được đưa ra bởi johncarl đã được chấp nhận nhưng nó không chính xác với tôi. JavaDocs cho CriteriaQuery.where() nói:

Sửa đổi truy vấn để hạn chế kết quả truy vấn theo biểu thức boolean được chỉ định. Thay thế các giới hạn đã được thêm trước đó, nếu có.

Theo tôi được biết, mỗi người trong số các dòng sau (cho các giới hạn) sẽ ghi đè lên các hạn chế được trước đó:

criteria.where(builder.like(langJoin.get(Language_.locale), locale)); 
criteria.where(builder.like(pRoot.get(Person_.name), name)); 
criteria.where(builder.between(pRoot.get(Person_.time), startDate, endDate)); 

Điều này có nghĩa rằng trong khi kết thúc chỉ giới hạn cuối cùng (giữa bắt đầu và ngày kết thúc) sẽ vẫn còn.

tôi threfore đề nghị sửa đổi câu trả lời johncarl của sau:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<Person> criteria = builder.createCriteria(Person.class); 
Root<Person> pRoot = criteria.from(Person.class); 
Join<Person, Language> langJoin = criteria.join("language", JoinType.LEFT); 

Predicate[] restrictions = new Predicate[] { 
    builder.like(langJoin.get(Language_.locale), locale), 
    builder.like(pRoot.get(Person_.name), name), 
    builder.between(pRoot.get(Person_.time), startDate, endDate) 
}; 

criteria.where(builder.and(restrictions)); 

criteria.orderBy(builder.asc(pRoot.get(Person_.name))); 

Tuy nhiên, mã này trông thật sự xấu xí! Xin vui lòng, cảm thấy tự do để chỉnh sửa nếu nó sai và bình luận nó nếu bạn nhìn thấy một giải pháp tốt hơn! Tôi sẽ rất duyên dáng!

+0

Cảm ơn Bạn đã thực sự cho gợi ý của bạn. criteria.where (...) không thể được sử dụng gia tăng, vì nó thay thế các tiêu chí có khả năng được truyền trước khi hoàn toàn. ở phía bên kia, một vấn đề duy nhất của builder.and ("mảng của các vị từ") hoạt động. Great giải pháp, pho312 :) – Hartmut

+0

Cảm ơn bạn đã gợi ý tuyệt vời! Tôi hoàn toàn yêu thích cách tiếp cận của bạn. Tôi chỉ đơn giản là thêm rằng một trong những có thể làm cho một ArrayList và chỉ cần thêm tiêu chí khi họ đến. Một mặt khác, tôi không biết tại sao nhưng pRoot.get (Person_.name) không làm việc cho tôi. Tôi nhận được lỗi với cú pháp Person_. – moldovean

Các vấn đề liên quan