繼上一篇文章對Spring Data JPA更深(
)一步剖析。
上一篇只是簡單的介紹了Spring Data JPA的簡單使用,而往往在項目中這一點功能並不能滿足我們的需求。這是當然的,在業務中查詢是一件非常頭疼的事,畢竟不可能只是對一張表的查詢是吧? 其實在業務中往往會涉及到多張表的查詢,以及查詢時需要的各種條件。當然這不用擔心,畢竟這是對JPA的支持,而我們在用JPA原生態API的時候往往可能會把一些個方法寫得很凌亂,沒得一個具體的規范來寫自己的方法在后期維護上肯定會很困難。當然你自己也可以封裝一些方法來使用,而當我們使用到Spring Data JPA時,它已經幫助我們完成了這個方法的規范了。
來一起看一下復雜查詢時它為我們提供的接口。
JpaSpecificationExecutor.class
- public interface JpaSpecificationExecutor<T> {
- T findOne(Specification<T> spec);
- List<T> findAll(Specification<T> spec);
- Page<T> findAll(Specification<T> spec, Pageable pageable);
- List<T> findAll(Specification<T> spec, Sort sort);
- long count(Specification<T> spec);
- }
在這個接口里面出現次數最多的類就是Specification.class,而這個類主要也就是圍繞Specification來打造的,Specification.class是Spring Data JPA提供的一個查詢規范,而你只需圍繞這個規范來設置你的查詢條件便可,我們來看一下Specification.class這個接口中有些什么東西。
Specification.class
- public interface Specification<T> {
- Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
- }
只有一個方法toPredicate,而其中的參數大家並不陌生,都是JPA規范中的,ROOT查詢中的條件表達式、CriteriaQuery條件查詢設計器、CriteriaBuilder條件查詢構造器,而我們在使用復雜對象查詢時,實現該方法用JPA去構造對象查詢便可。
下面來看一個小例子:
- @Repository("userDao")
- public interface IUserDao extends JpaSpecificationExecutor<User>{
- }
仍然只是一個空接口,這次繼承的是JpaSpecificationExecutor了。
再寫一測試用例:查詢用戶表中name包含Sam的記錄,並分頁按照birth排倒序
- public class UserDaoTest {
- private static ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
- private static IUserDao userDao = (IUserDao) context.getBean("userDao");
- public void findBySpecAndPaginate() {
- Page<User> page = userDao.findAll(new Specification<User>() {
- @Override
- public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
- root = query.from(User.class);
- Path<String> nameExp = root.get("name");
- return cb.like(nameExp, "%Sam%");
- }
- }, new PageRequest(1, 5, new Sort(Direction.DESC, new String[] { "birth" })));
- StringBuilder stout = new StringBuilder(" 以下是姓名包含Sam人員信息 : ").append("\n");
- stout.append("| 序號 | username | password | name | sex | birth |").append("\n");
- int sortIndex = 1;
- for (User u : page.getContent()) {
- stout.append(" | ").append(sortIndex);
- stout.append(" | ").append(u.getUsername());
- stout.append(" | ").append(u.getPassword());
- stout.append(" | ").append(u.getName());
- stout.append(" | ").append(u.getSex());
- stout.append(" | ").append(u.getBirth());
- stout.append(" | \n");
- sortIndex++;
- }
- System.err.println(stout);
- }
- public static void main(String[] args) {
- UserDaoTest test = new UserDaoTest();
- test.findBySpecAndPaginate();
- }
- }
當然,這只是一個測試,很簡單的一個條件查詢方法。你也可以設計復雜的查詢來得到自己所需的結果,我這只是寫一個很簡單的方法來帶大家入門。
寫了兩篇文章了,還沒有講Spring Data JPA為什么只需定義接口就可以使用,其實這也不難發現,查看源碼,可以找到針對JpaRepository和JpaSpecificationExecutor有一個實現類,SimpleJpaRepository.class,這個類實現了剛才所提的兩個接口。而Spring在給我們注入實現類的時候,就正是這個SimpleJpaRepository.class,具體的實現方式我就不在這意義贅述了,大家如果有興趣可以去查看它的源碼,和傳統的JPA實現是一樣的。
通過這篇文章我們學習到了,當要使用復雜的條件查詢時,我們可以選擇使用此接口來完善我們的需求,這篇文章就講到這里,在下一篇文章中我主要是講Spring Data JPA為我們提供的注解查詢。
轉自:http://z276356445t.iteye.com/blog/1602258

