Spring Data JPA 动态查询总结

最近接触到的项目要使用Spring Data JPA 的动态查询。学习了几天之后,以一个Student的小例子做一下总结。

1.定义StudentFilter,查询条件的集合,即通过ID和name来查询Student。

@Data
public class StudentFilter {
    private String id;
    private String name;
}

2.定义一个类StudentSpecs,查询方法的集合

public class StudentSpecs {	
	//方法1。Specification:规格,规范。Predicate:断言。将复杂的查询提取成一个方法。
    public static Specification<Student> getStudentByFilter(StudentFilter StudentFilter){	
        return new Specification<Student>() {//使用 Specification 的匿名内部类
            @Override
			/**
             * @param *root: 代表查询的实体类.
             * @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 
             * @param *cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂
             * @return: *Predicate 类型, 代表一个查询条件.
             */
            public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates  = new ArrayList<Predicate>();//将多个查询条件放在一个list中
                if(StudentFilter.getId() != null && !"".equals(StudentFilter.getId())){
                    predicates.add(criteriaBuilder.equal(root.<String>get("id"), StudentFilter.getId()));
                }
                if(StudentFilter.getName() != null && !"".equals(StudentFilter.getName())){
                    predicates.add(criteriaBuilder.equal(root.<String>get("name"), StudentFilter.getName()));
                }
				//criteriaBuilder.and()返回一个predicate对象
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }
	//还可以继续添加方法2
}

其中,criteriaBuilder.equal方法返回一个predicate对象,加入predicates list中,拆开写就是

String id = root.get("id");
Predicate predicateId = criteriaBuilder.equal(id, StudentFilter.getId());//equal表示过滤条件是相等
predicates.add(predicateId);

3.有一个类的Repository,继承JPA的JpaSpecificationExecutor

public interface StudentRepository extends DataRepository<Student, String>, JpaSpecificationExecutor<Student> {
}

4.Manager层,实例化一个Repository,然后定义查询方法,去调用repository的findAll方法,将之前Specification中的查询方法添加进去。这样的话,再有别的查询需求时,直接放到Specs里,然后repository的findAll中加入即可,可以与之前的查询方法and或者or

public class StudentManager {
    StudentRepository StudentRepository;
	public List<Student> getStudentByFilter(StudentFilter StudentFilter) {
		return  StudentRepository.findAll(StudentSpecs.getStudentByFilter(StudentFilter));
    }
}

5.Service层。这样写有个不好处是参数多的话会比较麻烦。后续看看怎么传递对象。

@GET
@Path("/student")
List<BizComponent> getStudentsByFilter(@QueryParam("id") String id,@QueryParam("name") String name);

6.Service Implement层。将从service层穿过来的参数赋值给对象,供查询方法调用

public List<Student> getStudentssByFilter(String id, String name,) {
	StudentFilter StudentFilter = new StudentFilter();
	StudentFilter.setId(id);
	return StudentManager.getStudentByFilter(StudentFilter);
}

7.test。先post两个学生实例,再进行查询,支持空状态查询。

@Test
public void testStudentGetMethod(){
	Student Student = new Student();
	Student.setId("1");
	Student.setName("1");

	Student Student1 = new Student();
	Student1.setId("2");
	Student1.setName("1");

	StudentService.post(Student);
	StudentService.post(Student1);

	Assert.assertEquals(2, StudentService.getStudentsByFilter("","",).size());
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值