项目day01—集成三大框架(Spring+SpringMVC+SpringDataJpa)
SpringDataJpa框架在原dao层上进一步优化
配置:
applicationContext.xml文件,加上(注意多了个data):xmlns:jpa=http://www.springframework.org/schema/data/jpa
<property name="packagesToScan" value="xxx.domain" />不再需要persistence.xml
<property name="generateDdl" value="false" />改为false
<jpa:repositories base-package="cn.itsource.pss.repository"
transaction-manager-ref="transactionManager"
entity-manager-factory-ref="entityManagerFactory" />配置SpringDataJpa
代码:
一、抽取父类:BaseDomain(@MappedSuperclass不持久化到数据库)
二、Repository: public interface _Repository extends JpaRepository<T, ID>{}//T是要操作的实体类,ID是实体类主键的类型如:<Employee,Long>
凡继承了JpaRepository 的接口:
自动实现CRUD(执行dao层entitymanger.save/.creatQuery等),自动创建bean(根据applicationContext里SpringDataJpa配置)
提供employeeRepository对象,使用时:
@Autowired
private EmployeeRepository employeeRepository;
如:employeeRepository.findAll();(框架自己实现entitymanger.creatQuery,geRtlist)
三、JpaRepository的基本功能(EmployeeRepository会继承)
- CRUD
使用:
List<Employee> list = employeeRepository.findAll();
Employee employee = employeeRepository.findOne(1L);
System.out.println(employeeRepository.count());
employeeRepository.save(employee);
employeeRepository.delete(103L);
- 排序和分页
使用:
Sort sort = new Sort(Sort.Direction.DESC,"username");
Pageable pageable = new PageRequest(0, 10,sort);
Page<Employee> page = employeeRepository.findAll(pageable);
List<Employee> list= employeeRepository.findAll(sort);不分页电话直接传(sort)
四、EmployeeRepository中补充方法
1、根据条件进行查询
List<Employee> findByUsernameLike(String username);
使用:employeeRepository. findByUsernameLike(“%1%”);
2、@Query注解查询 //Query的注解注入非常灵活,还可以写sql,jpql但是很复杂
@Query("select o from Employee o where o.age=?1 and o.email like ?2")
List<Employee> query03(int age,String email);
直接使用:employeeRepository. query03(25,”%2%”)
3、使用JpaSpecificationExecutor
需要让EmployeeRepository也继承JpaSpecificationExecutor
使用(修改红色部分实现功能,其余语法固定):
@Test public void test1() throws Exception{
Sort sort = new Sort(Sort.Direction.DESC, "id");
PageRequest pageRequest = new PageRequest(1, 10,sort); List<Employee> list = employeeRepository.findAll(new Specification<Employee>() { @Override public Predicate toPredicate(Root<Employee> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { Path unamePath = root.get("username"); Predicate p1= criteriaBuilder.like(unamePath, "%9%");
Path agePath = root.get("age");//泛型不删会报错
Predicate p2 = criteriaBuilder.gt(agePath,20);
Predicate predicate = criteriaBuilder.and(name, age); return predicate; } }, pageRequest);//整个new Specification(){}是一个参数,findAll(参数,参数)。 //List<Employee> list=emp.findAll(xxx, pageRequest); list.forEach(employee -> System.out.println(employee)); }
五、jpa-spec插件:来自wenhao(修改红色部分实现功能,其余语法固定):
@Test public void testJpaSpec03()throws Exception{ Sort sort = new Sort(Sort.Direction.valueOf("DESC"),"age"); Pageable pageable = new PageRequest(0,10,sort); //获取到查询的规则 Specification<Employee> spec = Specifications.<Employee>and() .like("username", "%1%") .build(); //根据规则完成查询 Page<Employee> page = employeeRepository.findAll(spec,pageable); page.forEach(e-> System.out.println(e)); }
- Query查询条件(方便与前台交接)
在后台集成各一个查询和分页功能,接受前台传来的不同数量种类的参数
1、查询写在子类EmployeeQuery(字段,setget)
@Override//兼容不同查询条件,StringUtils.isNotBlank
public Specification createSpec() {
Specification<Employee> spec = Specifications.<Employee>and()
.like(StringUtils.isNotBlank(username),"username", "%"+username+"%")
.like(StringUtils.isNotBlank(email),"email", "%"+email+"%")
.eq(departmentId!=null,"department.id",departmentId)
.gt(age!=null,"age", age)
.build();
return spec;
}
2、排序写在父类BaseQuery(字段,默认值,setget)
public Sort createSort(){
if(StringUtils.isNotBlank(orderName)){
return new Sort(Sort.Direction.valueOf(orderType.toUpperCase()),orderName);
}
return null;
}
使用:(四句代码)
Specification spec = query.createSpec();//后台集成的查询功能
Sort sort = query.createSort();//后台集成的排序功能
//分页:query的时候也把分页的参数set到了BaseQuery,(set了值,就会get到这个值,没set就默认值(1,10)) Pageable pageable = new PageRequest(query.getJpaCurrentPage(),query.getPageSize(),sort); Page<Employee> page = employeeRepository.findAll(spec,pageable);
六、SpringDataJpa扩展
//进一步优化,把创建 Sort和Pageable封装,只需要设置完query后直接.findByQuery(query)或.findPageByQuery(query)实现排序和分页(一句代码)
需要:BaseRepository、BaseRepositoryImpl、BaseRepositoryFactoryBean(具体内容和原理见代码)
BaseRepositoryImpl实现类(封装好Sort和Pageable,需要通过BaseQuery拿到查询和分页条件)
如: @Override
public Page findPageByQuery(BaseQuery baseQuery) {
Specification spec = baseQuery.createSpec();
Sort sort = baseQuery.createSort();
Pageable pageable = new PageRequest(baseQuery.getJpaCurrentPage(), baseQuery.getPageSize(),sort);
Page<T> page = super.findAll(spec, pageable);
return page;
}
使用:(一句代码)
List<Employee> list = employeeRepository.findByQuery(query)
或者:Page<Employee> page = employeeRepository.findPageByQuery(query);
@Test
public void testDiy() throws Exception{
EmployeeQuery query = new EmployeeQuery();
query.setUsername("1");
query.setEmail("2");
List<Employee> list = employeeRepository.findByQuery(query);//不需要分页
//Page<Employee> page = employeeRepository.findPageByQuery(query);//需要分页
list.forEach(employee -> System.out.println(employee));
}
//所以,如果不传分页参数,调用findByQuery,那就不会分页。 //不传分页参数,而又非要调用findPageByQuery,就会按默认值分页 //设置了分页参数,却调用findByQuery==无法分页 //设置了分页参数,调用findPageByQuery,按设置值分页
学习总结,方便自己看懂
by 李强,2019/7/6