在JPA中,如果用@Query查询有诸多不便,因此JPA提供了基于Criteria API的查询,比@Query查询更灵活方便,这篇文章就简单说说Specification的简单使用。
这篇文章是参考: Useing JPA Criteria API ,相关代码如下所示:
JpaSpecificationExecutor
的接口: import com.example.demo.dto.Customer; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; /** * Created by Administrator on 2017/7/12 0012. */ public interface CustomerSpecificationRepository extends JpaRepository<Customer,Long>, JpaSpecificationExecutor<Customer> { }
这里只是继承接口声明的方法,比如
T findOne(Specification<T> spec); List<T> findAll(Specification<T> spec); Page<T> findAll(Specification<T> spec, Pageable pageable); List<T> findAll(Specification<T> spec, Sort sort); long count(Specification<T> spec);
包含了常用的查询单个对象,查询数据集合,查询分页数据集合,查询带排序参数的数据集合,查询数据的大小,这些都是常用的数据结果集,因此可以不用做其他定义即可直接使用。
import org.springframework.data.jpa.domain.Specification; import javax.persistence.criteria.Path; /** * Created by Administrator on 2017/7/13 0013. */ public final class SpecificationFactory { public static Specification containsLike(String attribute, String value) { return (root, query, cb) -> cb.like(root.get(attribute), "%" + value + "%"); } public static Specification isBetween(String attribute, int min, int max) { return (root, query, cb) -> cb.between(root.get(attribute), min, max); } public static Specification isBetween(String attribute, double min, double max) { return (root, query, cb) -> cb.between(root.get(attribute), min, max); } public static <T extends Enum<T>> Specification enumMatcher(String attribute, T queriedValue) { return (root, query, cb) -> { Path<T> actualValue = root.get(attribute); if (queriedValue == null) { return null; } return cb.equal(actualValue, queriedValue); }; } }
这个工具类定义了一些基本的查询,包括模糊匹配(containsLike),数值区间(isBetween)以及枚举类参数匹配(enumMatcher),这些也是在查询中常用的方法,在查询的时候,通过Specifications进行调用组织参数,即可获得接口Specification的实例,然后用于查询。
@Autowired private CustomerSpecificationRepository csr;
@RequestMapping("/spec") public void specificationQuery(){ Specification<Customer> spec = SpecificationFactory.containsLike("lastName","bau"); Pageable pageable = new PageRequest(0,5, Sort.Direction.DESC,"id"); Page<Customer> page = csr.findAll(spec,pageable); System.out.println(page); System.out.println(page.getTotalElements()); System.out.println(page.getTotalPages()); for (Customer c:page.getContent()){ System.out.println(c.toString()); } }
@RequestMapping("/spec2") public void specificationQuery2(){ Specification<Customer> spec2 = Specifications .where(SpecificationFactory.containsLike("firstName","bau")) .or(SpecificationFactory.containsLike("lastName","bau")); Pageable pageable = new PageRequest(0,5, Sort.Direction.DESC,"id"); Page<Customer> page = csr.findAll(spec2,pageable); System.out.println(page); System.out.println(page.getTotalElements()); System.out.println(page.getTotalPages()); for (Customer c:page.getContent()){ System.out.println(c.toString()); } }
至此,使用Specification通过Criteria API进行查询,获得查询的结果集。相较于@Query方式的查询定义,更人性化和方便操作,后面在对Criteria API的使用进一步深入,会继续给出相关实践,敬请期待。
参考:
官方文档 ,
PDF官方文档下载
API官方文档
JPQL文档DEMO示例: https://github.com/icnws/spring-data-jpa-demo