2012-08-30 17 views
23

Potrzebuję wykonać metodę wyszukiwania, która używa interfejsu API JPA Kryteria z wieloma parametrami. Problem polega na tym, że nie każdy parametr jest wymagany. Niektóre mogą mieć wartość zerową i nie powinny być uwzględniane w kwerendzie. Próbowałem tego z CriteriaBuilder, ale nie mogłem zobaczyć, jak to działa.Interfejs API JPA z wieloma parametrami

Dzięki API Hibernate Criteria jest to dość łatwe. Po prostu stwórz kryteria, a następnie dodaj Ograniczenia.

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

Jak mogę to osiągnąć dzięki API Kryteriów JPA?

Odpowiedz

59

Concept jest skonstruować tablicę javax.persistence.Predicate który zawiera tylko predykaty chcemy użyć:

Przykład podmiotu być pytani:

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

Zapytanie sama:

//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

Jak uzyskać instancję 'em'? – Alex

+1

@Alex em, czyli EntityManager, prawdopodobnie zostałby automatycznie uwierzytelniony. Twoja klasa konfiguracyjna ustawi to w górę. –

3

Spójrz na tę stronę JPA Criteria JPA. Istnieje wiele przykładów.

Aktualizacja: Zapewnienie konkretny przykład

wyszukiwania Let dla kont z saldem niższej niż określonej wartości:

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

najpierw utworzyć Builder Criteria

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

Aby dostać wynik ustaw parametr (y) i uruchom zapytanie:

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

BTW: Obiekt entityManager jest wstrzykiwany gdzieś w EJB/Service/DAO.

+0

Jeśli nie ustawię parametru, jak to odzwierciedli w zapytaniu? Ponieważ wciąż muszę dołączyć inne parametry do CriteriaQuery. A jeśli jedna z nich jest zerowa, doprowadzi to do nieoczekiwanych rezultatów. – mokuril

0

odpowiedź Mikko pracował estetycznie. Jedyną zmianą, którą musiałem wykonać, było: Zamiast: cq.select (klient) .where (predicates.toArray (new Predicate [] {})); WYMIANA: Predykat [] predicatesarr = predicates.toArray (new Predicate [predicates.size()]); cq.select (klient) .where (predicatesarr);

Gdzieś nie doszło do konwersji z listy na tablicę w oryginale.

Powiązane problemy