一步步學習 Spring Data 系列之JPA(二)


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

上一篇只是簡單的介紹了Spring Data JPA的簡單使用,而往往在項目中這一點功能並不能滿足我們的需求。這是當然的,在業務中查詢是一件非常頭疼的事,畢竟不可能只是對一張表的查詢是吧? 其實在業務中往往會涉及到多張表的查詢,以及查詢時需要的各種條件。當然這不用擔心,畢竟這是對JPA的支持,而我們在用JPA原生態API的時候往往可能會把一些個方法寫得很凌亂,沒得一個具體的規范來寫自己的方法在后期維護上肯定會很困難。當然你自己也可以封裝一些方法來使用,而當我們使用到Spring Data JPA時,它已經幫助我們完成了這個方法的規范了。 

來一起看一下復雜查詢時它為我們提供的接口。 

JpaSpecificationExecutor.class 

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 

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為我們提供的注解查詢。 

轉自:http://z276356445t.iteye.com/blog/1602258


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM