2012-02-17 97 views
34

Bạn có thể vui lòng giúp tôi cách chuyển đổi các mã sau đây để sử dụng toán tử "in" của trình tạo tiêu chí không? Tôi cần lọc bằng cách sử dụng danh sách/mảng tên người dùng bằng "in".JPA CriteriaBuilder - Cách sử dụng toán tử so sánh "IN"

Tôi cũng đã cố gắng tìm kiếm bằng phương pháp JPA CriteriaBuilder - "in" nhưng không thể tìm thấy kết quả tốt. Vì vậy, tôi thực sự sẽ đánh giá cao nếu bạn có thể cung cấp cho tôi URL tham chiếu cho chủ đề này. Cảm ơn.

Đây là mã của tôi:

//usersList is a list of User that I need to put inside IN operator 

CriteriaBuilder builder = getJpaTemplate().getEntityManagerFactory().getCriteriaBuilder(); 
CriteriaQuery<ScheduleRequest> criteria = builder.createQuery(ScheduleRequest.class); 

Root<ScheduleRequest> scheduleRequest = criteria.from(ScheduleRequest.class); 
criteria = criteria.select(scheduleRequest); 

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

List<ParameterExpression<String>> usersIdsParamList = new ArrayList<ParameterExpression<String>>(); 

for (int i = 0; i < usersList.size(); i++) { 
ParameterExpression<String> usersIdsParam = builder.parameter(String.class); 
params.add(builder.equal(scheduleRequest.get("createdBy"), usersIdsParam)); 
usersIdsParamList.add(usersIdsParam); 
} 

criteria = criteria.where(params.toArray(new Predicate[0])); 

TypedQuery<ScheduleRequest> query = getJpaTemplate().getEntityManagerFactory().createEntityManager().createQuery(criteria); 

for (int i = 0; i < usersList.size(); i++) { 
query.setParameter(usersIdsParamList.get(i), usersList.get(i).getUsername()); 
} 

List<ScheduleRequest> scheduleRequestList = query.getResultList(); 

Các nội Query String được chuyển xuống dưới, vì vậy tôi không nhận được hồ sơ được tạo ra bởi hai người dùng, bởi vì nó được sử dụng "AND".

select generatedAlias0 from ScheduleRequest as generatedAlias0 where (generatedAlias0.createdBy=:param0) and (generatedAlias0.createdBy=:param1) order by generatedAlias0.trackingId asc 

Trả lời

69

Nếu tôi hiểu tốt, bạn muốn tham ScheduleRequest với User và áp dụng các quy định tại khoản in đến userName tài sản của đơn vị User.

Tôi cần làm việc một chút về lược đồ này. Nhưng bạn có thể thử với thủ thuật này, có thể đọc được nhiều hơn mã bạn đã đăng và tránh phần Join (vì nó xử lý logic Join bên ngoài Truy vấn tiêu chí).

List<String> myList = new ArrayList<String>(); 
for (User u : usersList) { 
    myList.add(u.getUsername()); 
} 
Expression<String> exp = scheduleRequest.get("createdBy"); 
Predicate predicate = exp.in(myList); 
criteria.where(predicate); 

Để viết nhiều kiểu an mã bạn cũng có thể sử dụng metamodel bằng cách thay thế dòng này:

Expression<String> exp = scheduleRequest.get("createdBy"); 

với điều này:

Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy); 

Nếu nó hoạt động, sau đó bạn có thể hãy thử thêm logic Join vào Criteria Query. Nhưng ngay bây giờ tôi không thể kiểm tra nó, vì vậy tôi thích để xem nếu ai đó khác muốn thử.

+0

Hi perissf, cảm ơn bạn đã trả lời. Tôi có thể hỏi xin vui lòng, "ScheduleRequest_" là gì? Làm thế nào để tôi tạo ra nó? – Jemru

+2

Đó là một lớp Metamodel được tạo tự động bởi nhà cung cấp JPA của bạn. Nếu bạn đang sử dụng Hibernate, hãy kiểm tra liên kết này http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/ – perissf

+0

Đọc mã giả của tôi Tôi thấy sự khác biệt về loại có thể xảy ra. Bạn đang tham gia với userNames (String) hoặc userIds (Integer/Long)? Xin vui lòng cho tôi biết để tôi có thể cập nhật câu trả lời của tôi – perissf

13

Không một câu trả lời hoàn hảo nào có thể là đoạn mã có thể hữu ích.

public <T> List<T> findListWhereInCondition(Class<T> clazz, 
      String conditionColumnName, Serializable... conditionColumnValues) { 
     QueryBuilder<T> queryBuilder = new QueryBuilder<T>(clazz); 
     addWhereInClause(queryBuilder, conditionColumnName, 
       conditionColumnValues); 
     queryBuilder.select(); 
     return queryBuilder.getResultList(); 

    } 


private <T> void addWhereInClause(QueryBuilder<T> queryBuilder, 
      String conditionColumnName, Serializable... conditionColumnValues) { 

     Path<Object> path = queryBuilder.root.get(conditionColumnName); 
     In<Object> in = queryBuilder.criteriaBuilder.in(path); 
     for (Serializable conditionColumnValue : conditionColumnValues) { 
      in.value(conditionColumnValue); 
     } 
     queryBuilder.criteriaQuery.where(in); 

    } 
+1

Cảm ơn rất nhiều @gbagga, điều này đã giúp tôi rất nhiều! phương thức trên (exp.in (myList)) sẽ không hoạt động khi bạn đang sử dụng "CriteriaBuilder". Phương pháp của bạn là phương pháp nên được sử dụng cho mệnh đề "IN" khi sử dụng tiêu chíBuilder. Thanh danh! – roneo

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