概述:SpringDataJpa是JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL的查询语句 ,是属于Spring的生成体系中的一部分。让操作数据库变得更加的简单,会自动完成crud,我们只需要调用方法就可以了
实现:
注意:
repository包就相当于dao层
需要实体管理对象工厂和事务管理器的支持
配置repository层(dao层)
创建一个接口,这个接口需要继承JpaRepository接口<1v,2v>
如果不实现则无法调用crud方法
该接口的两个参数:
1v:代表你要操作的是哪一个domain对象
2v:这个domain对象的主键的类型
但只能实现基本的crud,如果需要高级查询(带条件查询)还需要继承一个接口
JpaSpecificationExecutor
查询全部:
List emps = employeeRepository.findAll();
for (Employee emp :emps){ System.out.println(emp); }
查询单条是数据(根据id):
Employee employee = employeeRepository.findOne(id);
添加与修改都使用save(主要看对象有没有id):
employeeRepository.save(employee);
删除(根据id):
employeeRepository.delete(id);
分页排序查询
需要先创建一个page对象(注意:页数是从0开始计算【0就是第1页】)
Pageable pageable = new PageRequest(第几页, 每页个数);
进行查询
Page page = employeeRepository.findAll(pageable);//将page对象传入进去
page.getTotalElements() //总条数
page.getTotalPages() //总页数
page.getContent() //当前页数据
page.getNumber() //第几页
page.getNumberOfElements()//当前页有多少个数据
page.getSize() //每页条数
排序
//排序 :第一个参数是排序的规则(DESC/ASC) 后面参数是排序的字符
Sort sort = new Sort(Sort.Direction.DESC,"字段");//根据字段来进行升序或降序
List emps = employeeRepository.findAll(sort);//将sort对象传入进去
for (Employee emp : emps) {
System.out.println(emp);
}
排序与分页的集成
Sort sort = new Sort(Sort.Direction.DESC,“字段”);//根据字段来进行升序或降序
Pageable pageable = new PageRequest(0, 10,sort);//直接将排序对象加在分页对象参数中
带条件查询
按照规范创建查询方法,一般按照java驼峰式书写规范加一些特定关键字
例:
//根据名称模糊查询
List findByUsernameLike(String username);
@Query注解查询
不遵循查询方法的命名规则,可以使用@Query的方法进行查询
@Query(“jpql语句”)
概述:可以用于动态生成Query来满足我们业务中的各种复杂场景,只要简单实现toPredicate方法就可以实现复杂的查询
最基本的使用:
List list = employeeRepository.findAll(new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery> cq,
CriteriaBuilder cb) {
Path usernamePath = root.get("username");
Predicate p = cb.like(usernamePath, "%1%");
return p;
}
});
查询的基础上,参数创建一个Specification的匿名内部类,它泛型写对应的domain对象
List list = employeeRepository.findAll(new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery> cq,
CriteriaBuilder cb) {
//1.拿到username字段
Path usernamePath = root.get("username");
//2.拿到email字段
Path emailPath = root.get("email");
Path agePath = root.get("age");
//3.确定它们的查询关系
Predicate p1 = cb.like(usernamePath, "%1%");
Predicate p2 = cb.like(emailPath, "%2%");
Predicate p3 = cb.ge(agePath, 20);
//4.把条件结合起来
Predicate p = cb.and(p1,p2,p3);
return p;
}
});
概述:这是一个对于咱们刚才的动态生成Query功能的一个封装版,如果我们使用这个插件,在完成查询与分页的时候功能会简单不少
*
*
Specification spec = Specifications.and()
.like("username", "%1%") //查询条件
.build(); //相当于一个提交功能
List list = employeeRepository.findAll(spec);
注意:红色部分为扩展包
多条件查询:
//准备一个Query对象(当它是当前拿到的) 员工的查询类(一些特殊条件)
EmployeeQuery query = new EmployeeQuery();
//query.setUsername("1"); 设置查询条件
//query.setEmail("2"); 设置查询条件
//query.setAge(20); 设置查询条件
//如果没有传这个值,咱们就不做这个判断
Specification spec = Specifications.and()
.like(StringUtils.isNotBlank(query.getUsername()),"username", "%"+query.getUsername()+"%") //第一个参数判断是否有条件,有则按条件查询,没有则默认查询
.like(StringUtils.isNotBlank(query.getEmail()),"email", "%"+query.getEmail()+"%")
.gt(query.getAge()!=null,"age", query.getAge())
.build();
//准备排序对象
//Sort sort = new Sort(Sort.Direction.DESC,"username");
//准备分页对象
Pageable pageable = new PageRequest(0,5);
Page page = employeeRepository.findAll(spec,pageable);
准备查询条件的父类
父类中写公共的查询代码
好处:1.规范代码 2.抽取公共代码
抽取公共代码
抽取分页条件:
抽取排序功能:
排序功能都可能需要,所以在父查询中
private Boolean orderType=true; //排序的方式 true=DESC/false=ASC
private String orderField; //如果没有传这个值,就不排序
//拿到排序的对象
public Sort createSort(){
//判断是否需要排序
if(StringUtils.isNotBlank(orderField)){
Sort.Direction type = orderType?Sort.Direction.DESC:Sort.Direction.ASC;
return new Sort(type,orderField);
}
return null;
}
抽取特殊条件:
子类查询继承父查询,在子类查询中添加自己的条件
实现:父查询中添加抽象方法,子类拿到抽象方法并实现(规范子类的代码)
@Override
public Specification createSpec(){
Specification spec = Specifications.and()
.like(StringUtils.isNotBlank(username), "username", "%" + username + "%")
.like(StringUtils.isNotBlank(email), "email", "%" + email + "%")
.gt(age != null, "age", age)
.build();
return spec;
}
Query抽取的好处: