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

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

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

来一块儿看一下复杂查询时它为咱们提供的接口。 

JpaSpecificationExecutor.class app

Java代码   收藏代码
  1. public interface JpaSpecificationExecutor<T> {  
  2.   
  3.     T findOne(Specification<T> spec);  
  4.   
  5.     List<T> findAll(Specification<T> spec);  
  6.   
  7.     Page<T> findAll(Specification<T> spec, Pageable pageable);  
  8.   
  9.     List<T> findAll(Specification<T> spec, Sort sort);  
  10.   
  11.     long count(Specification<T> spec);  
  12. }  



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

Specification.class ide

Java代码   收藏代码
  1. public interface Specification<T> {  
  2.   
  3.     Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);  
  4. }  


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

下面来看一个小例子: 学习

Java代码   收藏代码
  1. @Repository("userDao")  
  2. public interface IUserDao extends JpaSpecificationExecutor<User>{  
  3. }  


仍然只是一个空接口,此次继承的是JpaSpecificationExecutor了。 
再写一测试用例:查询用户表中name包含Sam的记录,并分页按照birth排倒序 测试

Java代码   收藏代码
  1. public class UserDaoTest {  
  2.   
  3.     private static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");  
  4.   
  5.     private static IUserDao userDao = (IUserDao) context.getBean("userDao");  
  6.   
  7.     public void findBySpecAndPaginate() {  
  8.         Page<User> page = userDao.findAll(new Specification<User>() {  
  9.             @Override  
  10.             public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  11.                 root = query.from(User.class);  
  12.                 Path<String> nameExp = root.get("name");  
  13.                 return cb.like(nameExp, "%Sam%");  
  14.             }  
  15.   
  16.         }, new PageRequest(1, 5, new Sort(Direction.DESC, new String[] { "birth" })));  
  17.   
  18.         StringBuilder stout = new StringBuilder(" 如下是姓名包含Sam人员信息 : ").append("\n");  
  19.         stout.append("| 序号 | username | password | name | sex | birth |").append("\n");  
  20.         int sortIndex = 1;  
  21.         for (User u : page.getContent()) {  
  22.             stout.append(" | ").append(sortIndex);  
  23.             stout.append(" | ").append(u.getUsername());  
  24.             stout.append(" | ").append(u.getPassword());  
  25.             stout.append(" | ").append(u.getName());  
  26.             stout.append(" | ").append(u.getSex());  
  27.             stout.append(" | ").append(u.getBirth());  
  28.             stout.append(" | \n");  
  29.             sortIndex++;  
  30.         }  
  31.         System.err.println(stout);  
  32.     }  
  33.   
  34.     public static void main(String[] args) {  
  35.         UserDaoTest test = new UserDaoTest();  
  36.         test.findBySpecAndPaginate();  
  37.     }  
  38. }  



固然,这只是一个测试,很简单的一个条件查询方法。你也能够设计复杂的查询来获得本身所需的结果,我这只是写一个很简单的方法来带你们入门。 

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



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

转自:http://z276356445t.iteye.com/blog/1602258spa

相关文章
相关标签/搜索