您当前的位置: 首页 >  spring

梁云亮

暂无认证

  • 2浏览

    0关注

    1211博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

SpringBoot整合SpringDataJpa 之 JPASpecificationExecutor

梁云亮 发布时间:2020-02-08 13:48:50 ,浏览量:2

JPASpecificationExecutor接口是单独存在的,它主要是提供了多条件查询的支持(类似Hibernated 的Criteria的查询方式),并且可以在查询中添加排序与分页。

JpaSpecificationExecutor接口的使用一般要和Repository体系的接口一起使用。Dao对象其实是注入了一个代理对象,通过继承Repository体系接口完成代理对象SimpleJpaRepository实现类对象的注入。而JpaSpecificationExecutor对象不在Repository接口体系内那么就无法完成对象注入,所以要使用JpaSpecificationExecutor对象必须要实现Repository体系接口

JpaSpecificationExecutor主要提供了多条件查询的支持,并且可以在查询中添加分页和排序。

示例: 准备工作:

实体类:

@Entity
@Table(name = "tb_dept")
public class Dept {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer deptno;

    @Column
    private String dname;

    @Column
    private String loc;

    //……getter/setter、默认构造方法、全参构造方法
}
第一步:创建Maven项目,添加依赖:

    org.springframework.boot
    spring-boot-starter-data-jpa


    mysql
    mysql-connector-java
    runtime


    org.springframework.boot
    spring-boot-starter-test
    test


    junit
    junit
    4.12
    test

第二步:修改application.yml:
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/db_test?useSSL=false&serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF8&autoReconnect=true&failOverReadOnly=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        enable_lazy_load_no_trans: true
    show-sql: true
    open-in-view: false
第三步:提供测试代码: 测试代码框架
@RunWith(SpringRunner.class)
@SpringBootTest
@EnableAutoConfiguration
public class DeptDaoTest {
    @Autowired
    private DeptDao deptDao;
}
单条件查询
@Test
public void fun() {
    List depts = deptDao.findAll(new Specification() {
        @Override
        public Predicate toPredicate(Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) {
            return criteriaBuilder.equal(root.get("dname"),"sales");
        }
    });
    depts.forEach(System.out::println);
}

其中:

  • Specification接口:封装了查询信息
  • Predicate:封装了单个查询条件
  • Root:对查询对象属性的封装,比如我们这里是查询Dept,因此root可以看成是Dept,可以通过此对象获取实体对象字段从而进行条件的设置
  • CriteriaQuery:定义一个基本的查询
  • CriteriaBuilder:查询条件的构造器
多条件查询
  • 实现一:
@Test
public void fun2() {
    Specification spc = (root, criteriaQuery, criteriaBuilder) -> {
        Predicate p1 = criteriaBuilder.like(root.get("dname"), "%A%");
        Predicate p2 = criteriaBuilder.like(root.get("loc"), "%S%");
        // return criteriaBuilder.and(new Predicate[]{p1, p2});
        return criteriaBuilder.and(p1,p2);  //两个return效果一样
    };
    List depts = deptDao.findAll(spc);
    depts.forEach(System.out::println);
}
  • 实现二:
   @Test
    public void fun3(){
        Specification spc = (root, criteriaQuery, criteriaBuilder)->criteriaBuilder.and(criteriaBuilder.equal(root.get("dname"),"RESEARCH"),criteriaBuilder.equal(root.get("loc"),"DALLAS"));
        List depts= deptDao.findAll(spc);
        depts.forEach(System.out::println);
    }
  • 实现三:
@Test
public void fun4() {
    //第一个Specification定义了两个or的equal组合
    Specification s1 = (root, criteriaQuery, criteriaBuilder) -> {
        Predicate p1 = criteriaBuilder.equal(root.get("deptno"), "20");
        Predicate p2 = criteriaBuilder.equal(root.get("deptno"), "30");
        return criteriaBuilder.or(p1, p2);
    };
    //第二个Specification定义了两个or的like组合
    Specification s2 = (root, criteriaQuery, criteriaBuilder) -> {
        Predicate p1 = criteriaBuilder.like(root.get("dname"), "%S%");
        Predicate p2 = criteriaBuilder.like(root.get("loc"), "AS%");
        return criteriaBuilder.or(p1, p2);
    };
    //通过Specification将两个Specification连接起来,第一个条件加where,第二个是and
    List depts = deptDao.findAll(Specification.where(s1).and(s2));
    depts.forEach(System.out::println);
}
带条件的分页查询
@Test
public void fun5(){
    Specification spc = (root, criteriaQuery, criteriaBuilder)->criteriaBuilder.ge(root.get("deptno"),2);
    Page page = deptDao.findAll(spc, PageRequest.of(2,3)); //查询第1页
    page.getContent().stream().forEach(System.out::println);
}
排序
@Test
public void fun6(){
   Specification spc = (root, criteriaQuery, criteriaBuilder)->criteriaBuilder.ge(root.get("deptno"),2);
   List depts = deptDao.findAll(spc, Sort.by(Sort.Direction.DESC,"loc"));
   depts.stream().forEach(System.out::println);
}
分页+条件+排序
@Test
public void test7(){
    Specification spc = (root, criteriaQuery, criteriaBuilder)->criteriaBuilder.ge(root.get("deptno"),2);
    Page page = deptDao.findAll(spc, PageRequest.of(0, 3, Sort.by(Sort.Direction.DESC, "loc")));
    page.getContent().stream().forEach(System.out::println);
}
关注
打赏
1665409997
查看更多评论
立即登录/注册

微信扫码登录

0.0451s