一步步学习 Spring Data 系列之JPA(一)

上一篇 文章对Spring Data JPA更深( )一步剖析。

上一篇只是简单的介绍了Spring Data JPA的简单使用,而往往在项目中这一点功能并不能满足我们的需求。这是当然的,在业务中查询是一件非常头疼的事,毕竟不可能只是对一张表的查询是吧? 其实在业务中往往会涉及到多张表的查询,以及查询时需要的各种条件。当然这不用担心,毕竟这是对JPA的支持,而我们在用JPA原生态API的时候往往可能会把一些个方法写得很凌乱,没得一个具体的规范来写自己的方法在后期维护上肯定会很困难。当然你自己也可以封装一些方法来使用,而当我们使用到Spring Data JPA时,它已经帮助我们完成了这个方法的规范了。

来一起看一下复杂查询时它为我们提供的接口。

JpaSpecificationExecutor.class
Java代码 收藏代码
  1. publicinterfaceJpaSpecificationExecutor{
  2. TfindOne(Specificationspec);
  3. ListfindAll(Specificationspec);
  4. PagefindAll(Specificationspec,Pageablepageable);
  5. ListfindAll(Specificationspec,Sortsort);
  6. longcount(Specificationspec);
  7. }


在这个接口里面出现次数最多的类就是Specification.class,而这个类主要也就是围绕Specification来打造的,Specification.class是Spring Data JPA提供的一个查询规范,而你只需围绕这个规范来设置你的查询条件便可,我们来看一下Specification.class这个接口中有些什么东西。

Specification.class
Java代码 收藏代码
  1. publicinterfaceSpecification{
  2. PredicatetoPredicate(Rootroot,CriteriaQueryquery,CriteriaBuildercb);
  3. }

只有一个方法toPredicate,而其中的参数大家并不陌生,都是JPA规范中的,ROOT查询中的条件表达式、CriteriaQuery条件查询设计器、CriteriaBuilder条件查询构造器,而我们在使用复杂对象查询时,实现该方法用JPA去构造对象查询便可。

下面来看一个小例子:
Java代码 收藏代码
  1. @Repository("userDao")
  2. publicinterfaceIUserDaoextendsJpaSpecificationExecutor{

仍然只是一个空接口,这次继承的是JpaSpecificationExecutor了。
再写一测试用例:查询用户表中name包含Sam的记录,并分页按照birth排倒序
Java代码 收藏代码
  1. publicclassUserDaoTest{
  2. privatestaticApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");
  3. privatestaticIUserDaouserDao=(IUserDao)context.getBean("userDao");
  4. publicvoidfindBySpecAndPaginate(){
  5. Pagepage=userDao.findAll(newSpecification(){
  6. @Override
  7. publicPredicatetoPredicate(Rootroot,CriteriaQueryquery,CriteriaBuildercb){
  8. root=query.from(User.class);
  9. PathnameExp=root.get("name");
  10. returncb.like(nameExp,"%Sam%");
  11. }
  12. },newPageRequest(1,5,newSort(Direction.DESC,newString[]{"birth"})));
  13. StringBuilderstout=newStringBuilder("以下是姓名包含Sam人员信息:").append("\n");
  14. stout.append("|序号|username|password|name|sex|birth|").append("\n");
  15. intsortIndex=1;
  16. for(Useru:page.getContent()){
  17. stout.append("|").append(sortIndex);
  18. stout.append("|").append(u.getUsername());
  19. stout.append("|").append(u.getPassword());
  20. stout.append("|").append(u.getName());
  21. stout.append("|").append(u.getSex());
  22. stout.append("|").append(u.getBirth());
  23. stout.append("|\n");
  24. sortIndex++;
  25. }
  26. System.err.println(stout);
  27. }
  28. publicstaticvoidmain(String[]args){
  29. UserDaoTesttest=newUserDaoTest();
  30. test.findBySpecAndPaginate();
  31. }
  32. }


当然,这只是一个测试,很简单的一个条件查询方法。你也可以设计复杂的查询来得到自己所需的结果,我这只是写一个很简单的方法来带大家入门。

写了两篇文章了,还没有讲Spring Data JPA为什么只需定义接口就可以使用,其实这也不难发现,查看源码, 可以找到针对JpaRepository和JpaSpecificationExecutor有一个实现类,SimpleJpaRepository.class,这个类实现了刚才所提的两个接口 。而Spring在给我们注入实现类的时候,就正是这个SimpleJpaRepository.class,具体的实现方式我就不在这意义赘述了,大家如果有兴趣可以去查看它的源码,和传统的JPA实现是一样的。



通过这篇文章我们学习到了,当要使用复杂的条件查询时,我们可以选择使用此接口来完善我们的需求,这篇文章就讲到这里,在下一篇文章中我主要是讲Spring Data JPA为我们提供的注解查询。

你可能感兴趣的:(一步步学习 Spring Data 系列之JPA(一))