【1】配置和JAR包和之前的jpa单表查询一样,这里就不导入代码了
【2】有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在Spring Data JPA中可以通过JpaSpecificationExecutor接口查询。相比JPQL,其优势是类型安全,更加的面向对象。
这里我们要是用到Test单元测试,记得把这两个注解加到类前,不然不能使用Spring的配置
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {
【3】动态查询步骤
1.利用IOC导入我们要用的dao层接口
2.new出一个Specification接口,需要填写我们对哪个实体类进行操作
3.这个接口会自带一个Predicate类的方法,里面有三个参数,Root,CriteriaQuery,CriteriaBuilder,
Root,比较属性名称
CriteriaBuilder,查询方式
CriteriaQuery,代表一个顶层查询对象,用来自定义查询(大部分情况下不用)
4.用root.get(我们实现类中的属性)获得我们的属性参数
5.在用CriteriaBuilder.euqal(path,value),这里的equal不是我们String中的equal。得到predicate对象。
6.return predicate
7.调用我们接口的方法,因为接口继承了JpaRepository<,>和JpaSpecificationExecutor<r>
这两个接口里面都有findone方法,就是查询一个数据。JpaRepository中的findone(主键值)的参数填写的是主键,也就是根据主键查询,而JpaSpecificationExcutor中的finddone,里面填写的是Specification。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {
/*Spec动态查询*/
@Autowired
private CustmoerDao custmoerDao;
@Test
public void testSpec() {
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
//获取比较的属性
Path<Object> custName = root.get("custName");
//构造查询条件 select * from cst_custmoer where cust_name="kfc"
Predicate predicate = criteriaBuilder.equal(custName, "kfc");
return predicate;
}
};
Customer cus = custmoerDao.findOne(spec);
System.out.println(cus);
【2】利用动态进行联合查询
原理都一样,直接上代码,CriteriaBuilder中还有一个and方法,目的是把两个predicate结合到一起查询
@Test
public void testSpec2() {
Specification<Customer> spec = new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");
Path<Object> custIndustry = root.get("custIndustry");
Predicate predicate = criteriaBuilder.equal(custName, "kfc");
Predicate predicate1 = criteriaBuilder.equal(custIndustry, "中国石油大学周边");
Predicate and = criteriaBuilder.and(predicate, predicate1);
return and;
}
};
Customer one = custmoerDao.findOne(spec);
System.out.println(one);
【3】spec的模糊查询
这里需要说一下,equals方法是可以直接通过path对象进行比较的
而其他的方法,例如like,gt,ge,lt,需要根据path指定的数据类型,进行比较
gt:greaterThan ,比我们传入的value大的数据
lt:lessthan,比我们传入的value小的数据
ge:相当于大于等于
le:相当于小于等于
notEqual:不等于
like:模糊查询
notLike:查询的结果和like相反
比较的类型:path.as(数据类型.class)
这里如果查询出多个数据,那么就可以用Sort排序
@Test
public void testLikeFind(){
Specification<Customer> spec=new Specification<Customer>() {
public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Path<Object> custName = root.get("custName");
Predicate like = criteriaBuilder.like(custName.as(String.class), "K%");
return like;
}
};
// List<Customer> all = custmoerDao.findAll(spec);
// for (Customer customer : all) {
// System.out.println(customer);
// }
//排序查询
//需要写一个sort排序,第一个写规则,第二个参数写根据哪个属性排序
Sort sort=new Sort(Sort.Direction.DESC,"custId");
List<Customer> all = custmoerDao.findAll(spec, sort);
for (Customer customer : all) {
System.out.println(customer);
}
}
【4】分页查询
利用到Pageable,这个大家应该很熟悉了。第一个参数传查询页数,第二个参数传查询的数目。
/*分页查询,Pageable*/
@Test
public void testSpec4(){
Pageable pageable=new PageRequest(0,2);//参数1:当前查询页数,第二个每页查询数量
Page<Customer> all = custmoerDao.findAll(pageable);
System.out.println(all.getTotalElements());//查询总数据数
List<Customer> content = all.getContent();//获取数据
for (Customer customer : content) {
System.out.println(customer);
}
System.out.println(all.getTotalPages());//得到总页数
}