現在、私は次のSpring JPAリポジトリベースのカスタムクエリを使用していますが、正常に動作しますが、
@Query("SELECT usr FROM User usr WHERE usr.configurable = TRUE "
+ "AND (" +
"lower(usr.name) like lower(:filterText) OR lower(usr.userType.classType.displayName) like lower(:filterText) OR lower(usr.userType.model) like lower(:filterText)"
+ ")"
+ "")
public List<User> findByFilterText(@Param("filterText") String filterText, Sort sort);
フィルタテキストがコンマ区切り値になる場合、このクエリを変更する必要があります。しかし、次のように、それは動的なクエリになり、どのように実行できますか。
作成する必要がある動的クエリ、
String sql = "SELECT usr FROM User usr WHERE usr.configurable = TRUE";
for(String Word : filterText.split(",")) {
sql += " AND (lower(usr.name) like lower(:" + Word + ") OR lower(usr.userType.classType.displayName) like lower(:" + Word + ") OR lower(usr.userType.model) like lower(:" + Word + "))";
}
JB Nizetおよび spring-data documentation に従って、カスタムインターフェイス+リポジトリ実装を使用する必要があります。
メソッドを使用してインターフェースを作成します。
public interface MyEntityRepositoryCustom {
List<User> findByFilterText(Set<String> words);
}
実装を作成します。
@Repository
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager entityManager;
public List<User> findByFilterText(Set<String> words) {
// implementation below
}
}
既存のリポジトリインターフェイスで新しいインターフェイスを拡張します。
public interface MyEntityRepository extends JpaRepository<MyEntity, Long>, MyEntityRepositoryCustom {
// other query methods
}
最後に、メソッドを別の場所で呼び出します。
dao.findByFilterText(new HashSet<String>(Arrays.asList(filterText.split(","))));
クエリ実装
sql
変数を生成する方法、つまり、一部の文字列をクエリに連結する方法は不適切です。 これをしないでください。
連結するWord
は、 有効なJPQL識別子 、つまり:
の後に Java識別子の開始 が続き、オプションで Java識別子の部分 が続きます。つまり、CSVにfoo bar,baz
、使用しようとするfoo bar
を識別子として使用すると、例外が発生します。
代わりに CriteriaBuilder
を使用して、安全な方法でクエリを構築できます。
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();
}
私は自分で解決策を探していました:「カスタム」リポジトリインターフェースと実装の命名は非常に厳密です(そこにあるように Spring Data JPAにカスタムメソッドを追加する方法 )
したがって、明確にするために、コード全体:(ただし、@ beerbajayは正しかった)
カスタムメソッドインターフェイス
public interface MyEntityRepositoryCustom {
List<MyEntity> findSpecial();
}
カスタムメソッドの実装
public class MyEntityRepositoryImpl implements MyEntityRepositoryCustom {
@PersistenceContext
private EntityManager em;
//custom method implementation
public List<Object> findSpecial() {
List<Object> list = em.createNativeQuery("select name, value from T_MY_ENTITY").getResultList();
return list;
}
}
「元の」リポジトリ
@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity,Long>, MyEntityRepositoryCustom {
//original methods here... do not redefine findSpecial()...
}
新しいカスタムメソッドで「オリジナル」リポジトリを使用できるようになりました
@Service
public class MyService {
@Autowired
private DataRepository r;
public void doStuff() {
List<Object> list = r.findSpecial();
}
}
Spring Data JPAには、「仕様」でカスタムクエリと動的クエリを作成する方法があります。 Spring Data-Specifications
まず、JPARepository
またはCRUDRepository
を拡張するインターフェイスも_JpaSpecificationExecutor<...>
_を実装する必要があります。これで十分です。リポジトリに_Specification<...>
_オブジェクトを受け入れる新しいメソッドfindAll
が追加されました。メソッドtoPredicate(...)
をオーバーライドすることにより、Certeriaクエリの作成に使用されるメソッドBeerbajayを使用できます。 (ほぼ)任意のクエリを自由に構築できます。
_Specification<...> spec = new Specification<...>() {
@Override
public Predicate toPredicate(Root<...> entity, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> conditions = buildManyPredicates(cb, entity);
return cb.and(conditions.toArray(new Predicate[conditions.size()]));
}
};
repository.findAll(spec, PageRequest.of(0, 10));
_
これにより、カスタムインターフェイスに追加したメソッドを解析しようとするSpring Dataの問題が解決されます(カスタムインターフェイスがないため)