SpringDataJpa的Specification查询

来源:互联网 发布:电子商务软件教材 编辑:程序博客网 时间:2024/06/05 02:02

spring data jpa 通过创建方法名来做查询,只能做简单的查询,那如果我们要做复杂一些的查询呢,多条件分页怎么办,这里,spring data jpa为我们提供了JpaSpecificationExecutor接口,只要简单实现toPredicate方法就可以实现复杂的查询

1.首先让我们的接口继承于JpaSpecificationExecutor

[java] view plain copy
  1. public interface TaskDao extends JpaSpecificationExecutor<Task>{  
  2.   
  3. }  


2.JpaSpecificationExecutor提供了以下接口

[java] view plain copy
  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就是需要我们传进去的参数,它是一个接口
[java] view plain copy
  1. public interface Specification<T> {  
  2.   
  3.     Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);  
  4. }  

提供唯一的一个方法toPredicate,我们只要按照JPA 2.0 criteria api写好查询条件就可以了,关于JPA 2.0 criteria api的介绍和使用,欢迎参考
http://blog.csdn.net/dracotianlong/article/details/28445725
http://developer.51cto.com/art/200911/162722.htm

2.接下来我们在service bean

[java] view plain copy
  1. @Service  
  2. public class TaskService {  
  3.   
  4.     @Autowired TaskDao taskDao ;  
  5.   
  6.   
  7.     /** 
  8.      * 复杂查询测试 
  9.      * @param page 
  10.      * @param size 
  11.      * @return 
  12.      */  
  13.     public Page<Task> findBySepc(int page, int size){  
  14.   
  15.         PageRequest pageReq = this.buildPageRequest(page, size);  
  16.         Page<Task> tasks = this.taskDao.findAll(new MySpec(), pageReq);  
  17.   
  18.         return tasks;  
  19.   
  20.     }  
  21.   
  22.      /** 
  23.       * 建立分页排序请求  
  24.       * @param page 
  25.       * @param size 
  26.       * @return 
  27.       */  
  28.      private PageRequest buildPageRequest(int page, int size) {  
  29.            Sort sort = new Sort(Direction.DESC,"createTime");  
  30.            return new PageRequest(page,size, sort);  
  31.      }  
  32.   
  33.     /** 
  34.      * 建立查询条件 
  35.      * @author liuxg 
  36.      * @date 2016年3月30日 下午2:04:39 
  37.      */  
  38.     private class MySpec implements Specification<Task>{  
  39.   
  40.         @Override  
  41.         public Predicate toPredicate(Root<Task> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  42.   
  43.      //1.混合条件查询  
  44.           /*Path<String> exp1 = root.get("taskName"); 
  45.             Path<Date>  exp2 = root.get("createTime"); 
  46.             Path<String> exp3 = root.get("taskDetail"); 
  47.             Predicate predicate = cb.and(cb.like(exp1, "%taskName%"),cb.lessThan(exp2, new Date())); 
  48.             return cb.or(predicate,cb.equal(exp3, "kkk")); 
  49.  
  50.             类似的sql语句为: 
  51.             Hibernate:  
  52.                 select 
  53.                     count(task0_.id) as col_0_0_  
  54.                 from 
  55.                     tb_task task0_  
  56.                 where 
  57.                     ( 
  58.                         task0_.task_name like ? 
  59.                     )  
  60.                     and task0_.create_time<?  
  61.                     or task0_.task_detail=? 
  62.             */  
  63.   
  64.     //2.多表查询  
  65.         /*Join<Task,Project> join = root.join("project", JoinType.INNER); 
  66.             Path<String> exp4 = join.get("projectName"); 
  67.             return cb.like(exp4, "%projectName%"); 
  68.  
  69.             Hibernate:  
  70.             select 
  71.                 count(task0_.id) as col_0_0_  
  72.             from 
  73.                 tb_task task0_  
  74.             inner join 
  75.                 tb_project project1_  
  76.                     on task0_.project_id=project1_.id  
  77.             where 
  78.                 project1_.project_name like ?*/   
  79.            return null ;    
  80.         }  
  81.     }  
  82. }  
3.实体类task代码如下
[java] view plain copy
  1. @Entity  
  2. @Table(name = "tb_task")  
  3. public class Task {  
  4.   
  5.     private Long id ;  
  6.     private String taskName ;  
  7.     private Date createTime ;  
  8.     private Project project;  
  9.     private String taskDetail ;  
  10.   
  11.     @Id  
  12.     @GeneratedValue(strategy = GenerationType.IDENTITY)  
  13.     public Long getId() {  
  14.         return id;  
  15.     }  
  16.     public void setId(Long id) {  
  17.         this.id = id;  
  18.     }  
  19.   
  20.     @Column(name = "task_name")  
  21.     public String getTaskName() {  
  22.         return taskName;  
  23.     }  
  24.     public void setTaskName(String taskName) {  
  25.         this.taskName = taskName;  
  26.     }  
  27.   
  28.     @Column(name = "create_time")  
  29.     @DateTimeFormat(pattern = "yyyy-MM-dd hh:mm:ss")  
  30.     public Date getCreateTime() {  
  31.         return createTime;  
  32.     }  
  33.     public void setCreateTime(Date createTime) {  
  34.         this.createTime = createTime;  
  35.     }  
  36.   
  37.   
  38.     @Column(name = "task_detail")  
  39.     public String getTaskDetail() {  
  40.         return taskDetail;  
  41.     }  
  42.     public void setTaskDetail(String taskDetail) {  
  43.         this.taskDetail = taskDetail;  
  44.     }  
  45.   
  46.     @ManyToOne(fetch = FetchType.LAZY)  
  47.     @JoinColumn(name = "project_id")  
  48.     public Project getProject() {  
  49.         return project;  
  50.     }  
  51.     public void setProject(Project project) {  
  52.         this.project = project;  
  53.     }  
  54.   
  55. }  


通过重写toPredicate方法,返回一个查询 Predicate,spring data jpa会帮我们进行查询。

也许你觉得,每次都要写一个类来实现Specification很麻烦,那或许你可以这么写

[java] view plain copy
  1. public class TaskSpec {  
  2.   
  3.     public static Specification<Task> method1(){  
  4.   
  5.         return new Specification<Task>(){  
  6.             @Override  
  7.             public Predicate toPredicate(Root<Task> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  8.                 return null;  
  9.             }  
  10.   
  11.         };  
  12.     }  
  13.   
  14.     public static Specification<Task> method2(){  
  15.   
  16.         return new Specification<Task>(){  
  17.             @Override  
  18.             public Predicate toPredicate(Root<Task> root, CriteriaQuery<?> query, CriteriaBuilder cb) {  
  19.                 return null;  
  20.             }  
  21.   
  22.         };  
  23.     }  
  24.   
  25. }  

那么用的时候,我们就这么用
[java] view plain copy
  1. Page<Task> tasks = this.taskDao.findAll(TaskSpec.method1(), pageReq);  
JpaSpecificationExecutor的介绍就到这里,下次再看看怎么通过写hql或者sql语句来进行查询

转自:http://blog.csdn.net/yingxiake/article/details/51014223
原创粉丝点击