2012-08-30 48 views
23

Tôi cần phải thực hiện một phương pháp tìm kiếm sử dụng API tiêu chí JPA với nhiều thông số. Bây giờ vấn đề là không phải mọi tham số đều được yêu cầu. Vì vậy, một số có thể là null và chúng không nên được đưa vào truy vấn. Tôi đã thử điều này với CriteriaBuilder nhưng tôi không thể thấy cách làm cho nó hoạt động.API tiêu chí JPA với nhiều tham số

Với API tiêu chí Hibernate, điều này khá dễ dàng. Chỉ cần tạo tiêu chí và sau đó thêm Hạn chế.

Criteria criteria = session.createCriteria(someClass.class); 
if(someClass.getName() != null) { 
    criteria.add(Restrictions.like("name", someClass.getName()); 
} 

Làm cách nào để đạt được điều tương tự với API tiêu chí của JPA?

Trả lời

59

Concept là xây dựng hàng loạt các javax.persistence.Predicate mà chỉ chứa predicates chúng tôi muốn sử dụng:

Ví dụ thực thể được truy vấn:

@Entity 
public class A { 
    @Id private Long id;  
    String someAttribute; 
    String someOtherAttribute; 
    ... 
} 

Query bản thân:

//some parameters to your method 
    String param1 = "1"; 
    String paramNull = null; 

    CriteriaBuilder qb = em.getCriteriaBuilder(); 
    CriteriaQuery cq = qb.createQuery(); 
    Root<A> customer = cq.from(A.class); 

    //Constructing list of parameters 
    List<Predicate> predicates = new ArrayList<Predicate>(); 

    //Adding predicates in case of parameter not being null 
    if (param1 != null) { 
     predicates.add(
       qb.equal(customer.get("someAttribute"), param1)); 
    } 
    if (paramNull != null) { 
     predicates.add(
       qb.equal(customer.get("someOtherAttribute"), paramNull)); 
    } 
    //query itself 
    cq.select(customer) 
      .where(predicates.toArray(new Predicate[]{})); 
    //execute query and do something with result 
    em.createQuery(cq).getResultList(); 
+1

Làm thế nào để bạn có được cá thể 'em'? – Alex

+1

@Alex em, đó là EntityManager, có thể chỉ được autowired in. Lớp cấu hình của bạn sẽ thiết lập điều đó. –

3

Hãy xem trang web này JPA Criteria JPA. Có rất nhiều ví dụ.

Cập nhật: Cung cấp một ví dụ cụ thể

Hãy tìm kiếm cho tài khoản có số dư thấp hơn một giá trị cụ thể:

SELECT a FROM Account a WHERE a.balance < :value 

Đầu tiên tạo một Builder Tiêu chuẩn

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 

CriteriaQuery<Account> accountQuery = builder.createQuery(Account.class); 
Root<Account> accountRoot = accountQuery.from(Account.class); 
ParameterExpression<Double> value = builder.parameter(Double.class); 
accountQuery.select(accountRoot).where(builder.lt(accountRoot.get("balance"), value)); 

Để có được kết quả đặt tham số (s) và chạy truy vấn:

TypedQuery<Account> query = entityManager.createQuery(accountQuery); 
query.setParameter(value, 1234.5); 
List<Account> results = query.getResultList(); 

BTW: Thực thểQuản lý được tiêm ở đâu đó trong EJB/Dịch vụ/DAO.

+0

Nếu tôi không đặt tham số, điều này sẽ phản ánh như thế nào trong truy vấn? Vì tôi vẫn cần phải nối thêm các tham số khác vào CriteriaQuery. Và nếu một trong số đó là null, điều này sẽ dẫn đến kết quả không mong muốn. – mokuril

0

câu trả lời Mikko của làm việc đẹp. Chỉ thay đổi tôi cần làm là: Thay vì: cq.select (khách hàng) .where (predicates.toArray (new Predicate [] {})); THAY THẾ VỚI: Predicate [] predicatesarr = predicates.toArray (new Predicate [predicates.size()]); cq.select (khách hàng) .where (predicatesarr);

Đâu đó, chuyển đổi từ danh sách thành mảng trong bản gốc không hoạt động.

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