Per JB Nizet e la spring-data documentation, è necessario utilizzare un'interfaccia personalizzata + implementazione repository.
Creare un'interfaccia con il metodo:
public interface MyEntityRepositoryCustom {
List<User> findByFilterText(Set<String> words);
}
Creare un'implementazione:
@Repository
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List<User> findByFilterText(Set<String> words) {
// implementation below
}
}
Estendere la nuova interfaccia nell'interfaccia Repository esistente:
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntityRepositoryCustom {
// other query methods
}
Infine, chiamare il metodo da qualche altra parte:
dao.findByFilterText(new HashSet<String>(Arrays.asList(filterText.split(","))));
esecuzione di query
tuo metodo di produzione variabile sql
, vale a dire concatenando alcune stringhe nella query è male. Non farlo.
Il word
cui si concatenato deve essere un valid JPQL identifier, vale a dire una :
seguito da un java identifier start, eventualmente seguita da un java identifier part. Ciò significa che se il tuo CSV contiene foo bar,baz
, tenterai di utilizzare foo bar
come identificatore e otterrai un'eccezione.
È invece possibile utilizzare CriteriaBuilder
per costruire la query in modo sicuro:
public List<User> findByFilterText(Set<String> words) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<User> q = cb.createQuery(User.class);
Root<User> user = q.from(User.class);
Path<String> namePath = user.get("name");
Path<String> userTypeClassTypeDisplayName =
user.get("userType").get("classType").get("displayName");
Path<String> userTypeModel = user.get("userType").get("model");
List<Predicate> predicates = new ArrayList<>();
for(String word : words) {
Expression<String> wordLiteral = cb.literal(word);
predicates.add(
cb.or(
cb.like(cb.lower(namePath), cb.lower(wordLiteral)),
cb.like(cb.lower(userTypeClassTypeDisplayName),
cb.lower(wordLiteral)),
cb.like(cb.lower(userTypeModel), cb.lower(wordLiteral))
)
);
}
q.select(doc).where(
cb.and(predicates.toArray(new Predicate[predicates.size()]))
);
return entityManager.createQuery(q).getResultList();
}
guarda in 'JpaSpecificationExecutor' –
Fornire un'implementazione per il proprio DAO ed eseguire questa query dinamica dall'implementazione. http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.single-repository-behaviour. Il DAO non dovrebbe dividersi. Dovrebbe richiedere un elenco o un Set come argomento. Il chiamante dovrebbe occuparsi della divisione. –