Per JB Nizet und die spring-data documentation, sollten Sie eine benutzerdefinierte Schnittstelle + Repository-Implementierung verwenden.
Eine Schnittstelle mit der Methode:
public interface MyEntityRepositoryCustom {
List<User> findByFilterText(Set<String> words);
}
eine Implementierung erstellen:
@Repository
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List<User> findByFilterText(Set<String> words) {
// implementation below
}
}
Erweitern Sie die neue Schnittstelle in Ihrer vorhandenen Repository-Schnittstelle:
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntityRepositoryCustom {
// other query methods
}
Schließlich fordern die Methode woanders:
dao.findByFilterText(new HashSet<String>(Arrays.asList(filterText.split(","))));
Abfrage Implementierung
Ihr Verfahren zur Herstellung der sql
variable Herstellung, nämlich durch einige Strings verketten in die Abfrage schlecht ist. Tun Sie das nicht.
Die word
, die Ihnen eine valid JPQL identifier sein werden verketten müssen, nämlich ein :
von einem java identifier start gefolgt gegebenenfalls von einigen java identifier part gefolgt. Wenn Ihre CSV-Datei foo bar,baz
enthält, werden Sie versuchen, foo bar
als Kennung zu verwenden, und Sie erhalten eine Ausnahme.
Sie können stattdessen CriteriaBuilder
verwenden, um die Abfrage in einer sicheren Weise zu konstruieren:
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();
}
verwenden können schauen Sie in 'JpaSpecificationExecutor' –
Stellen Sie eine Implementierung für Ihr DAO bereit und führen Sie diese dynamische Abfrage von der Implementierung aus. http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.single-repository-behaviour. Die DAO sollte nicht aufgeteilt werden. Es sollte eine Liste oder ein Set als Argument nehmen. Der Anrufer sollte sich mit dem Aufteilen befassen. –