繼上一篇文章對Spring Data JPA更深( )一步剖析。
上一篇只是簡單的介紹了Spring Data JPA的簡單使用,而每每在項目中這一點功能並不能知足咱們的需求。這是固然的,在業務中查詢是一件很是頭疼的事,畢竟不可能只是對一張表的查詢是吧? 其實在業務中每每會涉及到多張表的查詢,以及查詢時須要的各類條件。固然這不用擔憂,畢竟這是對JPA的支持,而咱們在用JPA原生態API的時候每每可能會把一些個方法寫得很凌亂,沒得一個具體的規範來寫本身的方法在後期維護上確定會很困難。固然你本身也能夠封裝一些方法來使用,而當咱們使用到Spring Data JPA時,它已經幫助咱們完成了這個方法的規範了。
來一塊兒看一下複雜查詢時它爲咱們提供的接口。
JpaSpecificationExecutor.class app
- 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 ide
- 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爲咱們提供的註解查詢。 ui
轉自:http://z276356445t.iteye.com/blog/1602258spa