智能销售系统day1

springdatajpa

1.SpringDataJpa

概述:SpringDataJpa是JPA规范的再次封装抽象,底层还是使用了Hibernate的JPA技术实现,引用JPQL的查询语句 ,是属于Spring的生成体系中的一部分。让操作数据库变得更加的简单,会自动完成crud,我们只需要调用方法就可以了

实现:

  1. 导包
    spring-data-jpa SpringData的支持包
  2. 基本配置
    在Spring.xml配置文件中配置
    前提:已经配置了数据库+实体管理对象工厂+事务管理器
    配置对应的Spring-data-jpa


注意:

  1. repository包就相当于dao层

  2. 需要实体管理对象工厂和事务管理器的支持

  3. 配置repository层(dao层)
    创建一个接口,这个接口需要继承JpaRepository接口<1v,2v>
    如果不实现则无法调用crud方法
    该接口的两个参数:
    1v:代表你要操作的是哪一个domain对象
    2v:这个domain对象的主键的类型

但只能实现基本的crud,如果需要高级查询(带条件查询)还需要继承一个接口
JpaSpecificationExecutor

2.JpaRepository的基本功能

  1. CRUD
    自动注入实现了JpaRepository接口的对象
    @Autowired
    private EmployeeRepository employeeRepository;

查询全部:

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);
  1. 分页排序查询
    需要先创建一个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() //每页条数

  2. 排序

//排序 :第一个参数是排序的规则(DESC/ASC)  后面参数是排序的字符
   Sort sort = new Sort(Sort.Direction.DESC,"字段");//根据字段来进行升序或降序
   List emps = employeeRepository.findAll(sort);//将sort对象传入进去
   for (Employee emp : emps) {
       System.out.println(emp);
   }
  1. 排序与分页的集成
    Sort sort = new Sort(Sort.Direction.DESC,“字段”);//根据字段来进行升序或降序
    Pageable pageable = new PageRequest(0, 10,sort);//直接将排序对象加在分页对象参数中

  2. 带条件查询
    按照规范创建查询方法,一般按照java驼峰式书写规范加一些特定关键字
    例:
    //根据名称模糊查询
    List findByUsernameLike(String username);

  3. @Query注解查询
    不遵循查询方法的命名规则,可以使用@Query的方法进行查询
    @Query(“jpql语句”)

3.JpaSpecificationExecutor的使用

概述:可以用于动态生成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对象

  1. 参数:
    root:(根)它可以帮我们拿到条件字段
    criteriaQuery:query:代表一个specific的顶层查询对象,把多个条件结合起来,可以分组排序!
    criteriaBuilder:条件字段的方式由它决定(=,>=,<,like,…)
    Predicate: 整个查询条件(where username like ? and email like ? and …)
    多条件查询:
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;
            }
        });

4.jpa-spec的使用

概述:这是一个对于咱们刚才的动态生成Query功能的一个封装版,如果我们使用这个插件,在完成查询与分页的时候功能会简单不少

  1. 导包
    jpa-spec SpringData的扩展包
    把所有的依赖都过滤掉

     
      *
      *
     

  1. 使用
    基本使用:
 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);

5.Query抽取

  1. 准备查询条件的父类
    父类中写公共的查询代码
    好处:1.规范代码 2.抽取公共代码

  2. 抽取公共代码
    抽取分页条件:

    1. 前台页数是从1开始的,而后台是从0开始
    2. 所以从前台传过来的数据需要-1

抽取排序功能:
排序功能都可能需要,所以在父查询中
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抽取的好处:

  1. 可以直接拿到数据,不用对象再去调用
  2. 代码简单了一些,查询时只需要调用规则就可以了

你可能感兴趣的:(智能销售系统day1)