Quando si utilizza l'API dei criteri JPA, qual è il vantaggio dell'utilizzo di ParameterExpression su una variabile direttamente? Per esempio. quando voglio cercare un cliente per nome in una variabile String, potrei scrivere qualcosa di simile autilizzando ParameterExpression rispetto a una variabile nell'API dei criteri JPA
private List<Customer> findCustomer(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class);
Root<Customer> customer = criteriaQuery.from(Customer.class);
criteriaQuery.select(customer).where(cb.equal(customer.get("name"), name));
return em.createQuery(criteriaQuery).getResultList();
}
Con parametri questo diventa:
private List<Customer> findCustomerWithParam(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Customer> criteriaQuery = cb.createQuery(Customer.class);
Root<Customer> customer = criteriaQuery.from(Customer.class);
ParameterExpression<String> nameParameter = cb.parameter(String.class, "name");
criteriaQuery.select(customer).where(cb.equal(customer.get("name"), nameParameter));
return em.createQuery(criteriaQuery).setParameter("name", name).getResultList();
}
Per concisione io preferirei il primo modo, soprattutto quando la query si allunga con parametri opzionali. Ci sono degli svantaggi nell'utilizzare parametri come questo, come l'iniezione SQL?
Non posso parlare per JPA in generale , ma ho scoperto che OpenJPA converte internamente una query Criteria in JPQL e questa può essere stampata usando la funzionalità specifica di OpenJPA (vedi htt p: //openjpa.apache.org/builds/2.1.1/apache-openjpa/docs/ch13s03.html). La prima query si traduce in "SELECT c FROM Customer c WHERE c.name = 'test Customer'". Ciò significa che NON usa un parametro, quindi se questo viene ulteriormente tradotto in SQL, l'istruzione preparata corrispondente NON utilizzerà un parametro. La seconda versione si traduce in JPQL "SELECT c FROM Customer c WHERE c.name =: name", quindi userò i parametri. –
Dopo alcuni test ho scoperto che scrivere la stessa query con JPQL e usare il nome "'OR' x '=' x" inietta JPQL. Quando si utilizza l'API dei criteri, il JPQL generato che OpenJPA registra sembra esattamente lo stesso. Tuttavia, l'attuale SQL registrato da OpenJPA utilizza quindi un'istruzione preparata con un parametro di valore "'OR' x '=' x" invece di '' nel caso JPQL.Ciò significa che l'iniezione SQL non funziona qui! Sfortunatamente non ho idea di quanto sia affidabile. Sembra che questa sia una funzionalità non documentata. –
Suggerimento: ho appena provato http://www.querydsl.com/ e la sintassi è molto più concisa e leggibile. Sembra difendersi dall'iniezione sql usando i parametri di default. –