一般在写业务接口的过程中,很有可能需要实现可以动态组合各种查询条件的接口。如果我们根据一种查询条件组合一个方法的做法来写,那么将会有大量方法存在,繁琐,维护起来相当困难。想要实现动态查询,其实就是要实现拼接SQL语句。
定义sql文件默认与实体类名字相同如:Sample.sftl
-- findByContent SELECT * FROM t_sample WHERE 1 = 1 <#if content??> AND content LIKE :content </#if> --countContent SELECT count(*) FROM t_sample WHERE 1 = 1 <#if content??> AND content LIKE :content </#if> --findDtos SELECT id, content as contentShow FROM t_sample --findByTemplateQueryObject SELECT * FROM t_sample WHERE 1 = 1 <#if content??> AND content LIKE :content </#if> --findMap SELECT * FROM t_sample
<?xml version="1.0" encoding="utf-8" ?> <sqls xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.slyak.com/schema/templatequery" xsi:schemaLocation="http://www.slyak.com/schema/templatequery http://www.slyak.com/schema/templatequery.xsd"> <sql name="findByContent"> <![CDATA[ SELECT * FROM t_sample WHERE 1=1 <#if content??> AND content LIKE :content </#if> ]]> </sql> <sql name="countContent"> <![CDATA[ SELECT count(*) FROM t_sample WHERE 1=1 <#if content??> AND content LIKE :content </#if> ]]> </sql> <sql name="findDtos"> <![CDATA[ SELECT id,content as contentShow FROM t_sample ]]> </sql> <sql name="findByTemplateQueryObject"> <![CDATA[ SELECT * FROM t_sample WHERE 1=1 <#if content??> AND content LIKE :content </#if> ]]> </sql> </sqls>
public interface SampleRepository extends GenericJpaRepository<Sample, Long> { @TemplateQuery Page<Sample> findByContent(String content, Pageable pageable); @TemplateQuery List<Sample> findByTemplateQueryObject(SampleQuery sampleQuery, Pageable pageable); @TemplateQuery Long countContent(String content); @TemplateQuery List<SampleDTO> findDtos(); // #{name?:'and content like :name'} @Query(nativeQuery = true, value = "select * from t_sample where content like ?1") List<Sample> findDtos2(String name); @TemplateQuery List<Map<String,Object>> findMap(); }
TemplateQuery.java
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD }) @QueryAnnotation @Documented public @interface TemplateQuery { String value() default ""; }
@Override protected QueryLookupStrategy getQueryLookupStrategy(QueryLookupStrategy.Key key, EvaluationContextProvider evaluationContextProvider) { return TemplateQueryLookupStrategy.create(entityManager, key, extractor, evaluationContextProvider); }
TemplateQueryLookupStrategy 模版查询策略 其中关键代码:
@Override public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, ProjectionFactory factory, NamedQueries namedQueries) { if (method.getAnnotation(TemplateQuery.class) == null) { return jpaQueryLookupStrategy.resolveQuery(method, metadata, factory, namedQueries); } else { return new FreemarkerTemplateQuery(new JpaQueryMethod(method, metadata, factory, extractor), entityManager); } }
@Override protected TypedQuery<Long> doCreateCountQuery(Object[] values) { TypedQuery query = (TypedQuery) getEntityManager() .createNativeQuery(QueryBuilder.toCountQuery(getQuery(values))); bind(query, values); return query; }