SpringDataJpa Specification查询方式

面试:你懂什么是分布式系统吗?Redis分布式锁都不会?>>>   hot3.png

Specifications动态查询

有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;

/**
 *	JpaSpecificationExecutor中定义的方法
 **/
 public interface JpaSpecificationExecutor {
   	//根据条件查询一个对象
 	T findOne(Specification spec);	
   	//根据条件查询集合
 	List findAll(Specification spec);
   	//根据条件分页查询
 	Page findAll(Specification spec, Pageable pageable);
   	//排序查询查询
 	List findAll(Specification spec, Sort sort);
   	//统计查询
 	long count(Specification spec);
}

对于JpaSpecificationExecutor,这个接口基本是围绕着Specification接口来定义的。我们可以简单的理解为,Specification构造的就是查询条件。

Specification接口中只定义了如下一个方法:

    //构造查询条件
    /**
    *	root	:Root接口,代表查询的根对象,可以通过root获取实体中的属性
    *	query	:代表一个顶层查询对象,用来自定义查询
    *	cb		:用来构建查询,此对象里有很多条件方法
    **/
    public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb);

1.1使用Specifications完成条件查询

	//依赖注入customerDao
	@Autowired
	private CustomerDao customerDao;	
	@Test
	public void testSpecifications() {
      	//使用匿名内部类的方式,创建一个Specification的实现类,并实现toPredicate方法
		Specification  spec = new Specification() {
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
				//cb:构建查询,添加查询方式   like:模糊匹配
				//root:从实体Customer对象中按照custName属性进行查询
				return cb.like(root.get("custName").as(String.class), "传智播客%");
			}
		};
		Customer customer = customerDao.findOne(spec);
		System.out.println(customer);
	}

1.2基于Specifications的分页查询

    @Test
	public void testPage() {
		//构造查询条件
		Specification spec = new Specification() {
			public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
				return cb.like(root.get("custName").as(String.class), "传智%");
			}
		};
		
		/**
		 * 构造分页参数
		 * 		Pageable : 接口
		 * 			PageRequest实现了Pageable接口,调用构造方法的形式构造
		 * 				第一个参数:页码(从0开始)
		 * 				第二个参数:每页查询条数
		 */
		Pageable pageable = new PageRequest(0, 5);
		
		/**
		 * 分页查询,封装为Spring Data Jpa 内部的page bean
		 * 		此重载的findAll方法为分页方法需要两个参数
		 * 			第一个参数:查询条件Specification
		 * 			第二个参数:分页参数
		 */
		Page page = customerDao.findAll(spec,pageable);
		
	}

值得注意的是其实排序和分页是可以同时查询的,Pageable的构造方法有

Pageable pageable = new PageRequest(PageNum, PageSize,new Sort());

对于Spring Data JPA中的分页查询,是其内部自动实现的封装过程,返回的是一个Spring Data JPA提供的pageBean对象。其中的方法说明如下:

//获取总页数
int getTotalPages();
 //获取总记录数	
long getTotalElements();
//获取列表数据
List getContent();

1.3方法对应关系 | 方法名称 | Sql对应关系 | | ------------ | ------------ | | equle | filed = value | | gt(greaterThan ) | filed > value | | lt(lessThan ) | filed < value | | ge(greaterThanOrEqualTo ) | filed >= value | | le( lessThanOrEqualTo) | filed <= value | | notEqule | filed != value | | like | filed like value | | notLike | filed not like value |

你可能感兴趣的:(SpringDataJpa Specification查询方式)