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 getStudentByFilter(StudentFilter StudentFilter){	
        return new Specification() {//使用 Specification 的匿名内部类
            @Override
			/**
             * @param *root: 代表查询的实体类.
             * @param query: 可以从中可到 Root 对象, 即告知 JPA Criteria 查询要查询哪一个实体类. 
             * @param *cb: CriteriaBuilder 对象. 用于创建 Criteria 相关对象的工厂
             * @return: *Predicate 类型, 代表一个查询条件.
             */
            public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List predicates  = new ArrayList();//将多个查询条件放在一个list中
                if(StudentFilter.getId() != null && !"".equals(StudentFilter.getId())){
                    predicates.add(criteriaBuilder.equal(root.get("id"), StudentFilter.getId()));
                }
                if(StudentFilter.getName() != null && !"".equals(StudentFilter.getName())){
                    predicates.add(criteriaBuilder.equal(root.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, JpaSpecificationExecutor {
}

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

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

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

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

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

public List 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());
}

 

你可能感兴趣的:(Spring,Boot)