SpringDataJPA的個人理解

1.項目集成Spring


    1.開發核心包 :導入context包  
    2.AOP支持 :導入Aspects包
    3.測試集成 : 導入test包
    4.web集成,配置監聽器: 導入web包
    5.整合持久層框架: 導入orm包
    
    6.在web.xml中配置spring的監聽器;
    
2.Spring整合JPA


    1.在applicationContext.xml中配置連接池;
    2.JPA配置 類似於 Hibernate的配置 ,因爲Hibernate就是JPA的一個實現,所以準確地說是Hibernate的配置
    與JPA很像:但是我們先學習的是Hibernate,就先入爲主,我們比較瞭解Hibernate的配置,然後來類比學習JPA的
    配置:
        Hibernate的 :LocalSessionFactoryBean  (SessionFactory的工廠)
        JPA的: LocalContainerEntityManagerFactoryBean (EntityManagerFactory的工廠);
        
        Hibernate的 :SessionFactory 
        JPA的: EntityManagerFactory
        
        以前我們Spring整合Hibernate是讓 Spring接管SessionFactory, 
        現在我們Spring整合JPA是讓Spring接管EntityManagerFactory;
        
        因爲對象關係映射 使 java的對象與數據庫的表建立了一一對應的關係,所以我們使用JPA對數據庫進行CRUD
        操作,已經不再直接面向數據庫了,而是面向java對象實體,所以JPA中的核心對象就是 實體管理對象,即
        EntityManager,Hibernate作爲一個JPA的實現,它的 Session 其實就是 EntityManager的實現,因爲雖然在JDBC
        階段我們操作數據庫時使用的是 Connection,但是一有了 對象關係映射(orm) ,對象與實體間已經建立了連接,
        我們操作的數據庫不再面向 Connection ,而是面向對象實體了, 在Hibernate中我們說 Session就相當於是
        JDBC中的 Connection ,這樣說只是爲了便於我們利用 JDBC中的一些只是來理解Hibernate,其實這樣說是不對的,
        因爲我們現在看來,這個Session 是一個實體管理器,它是面向實體的,而JDBC中的 Connection 確實隱藏在實體中,
        
        所以準確地說 Session 其實是通過 實體來操作 Connection ,進而實現了 類似 JDBC 操作;        
        關於這個理解,我們從SessionFactory的配置中就可以看出來,它裏邊有:
            1. DataSource(連接池),
            2. Hibernate一些基本設置:比如方言,自動建表,顯示建表語句等等,
            3. Mapping(orm)         
        也就是說 SessionFactory 做爲Session的工廠,在生產Session是時,將 DataSource 與 Mapping進行了融合,最終
        給我們生成出來的 Session 其實已經包含了對象關係映射和連接,這樣導致它可以直接面向實體對象, 達到操作
        數據庫表的效果;
        
    3.聲明式事務管理:(用什麼框架就用響應的事務管理器)
        爲什麼是這樣呢?我們在JDBC階段就知道事務管理的本質是通過Connection來實現的,在不同的 持久層 框架中,Connection
        被封裝在不同的對象中:
            在Hibernate框架中, Connection 被封裝到 SessionFactory 中,
            在JPA中 , Connection 被封裝到 EntityManagerFactory 中;
        這就導致了,我們在使用不同框架進行聲明式事務管理時,要獲得Connection就要使用不同的對象;就是不同的事務管理器;    
    
3. SpringDataJPA 查詢 (其實只是 封裝了SQL語句)
    1.出現目的:爲了簡化統一持久層各種實現技術的API; 所以 SpringDataJPA 提供了一套標準API 和不同持久層整合技術實現;
     
    2. Spring-data-commens 一套標準API  比如 JpaRepository.class就在 這個jar包下 ;
       Spring-data-jpa 基於整合JPA的一套實現; 
        
    3.具體操作:
        1.寫一個接口(比如Dao層接口)繼承 JPARepository接口 (或者QBC查詢:JpaSpecificationExecutor接口)
        2.我們在 Dao 接口裏邊 就可以調用 JPARepository 接口的方法, JPARepository有一個默認實現類:
            SimpleJpaRepository,當我們 調用獲得Dao接口對象時,得到的是接口的子類代理對象proxy,當我們
            調用這個代理對象proxy的方法時, 實際調用的是 SimpleJpaRepository的方法;這樣實現一些既定的
            CRUD操作;
            
        3. 但是自帶的API中沒有條件查詢,這個時候我們就要用到 Spring data Query:
            1.根據方法命名規則 命名方法,自動生成 JPQL查詢;
                個人理解:我們通過方法命名規則不難看出,它底層實際是將方法名和傳入參數解釋成了一條查詢語句,
                        所以只要你按照他的規則命名,並且傳入相應的參數,它就知道如何轉換成一條JPQL語句;如果
                        類比理解,你自定義的Dao就是 QueryRunner ,你自定義的方法就是 sql語句; 它是首先將一些
                        常用的CRUD封裝好了,需要參數出入的,它給你提供方法,讓你傳入參數; 對於一些複雜的條件
                        查詢,它可能是沒辦法給給你全都封裝好,所以就給你提供了一個方法命名規則,然後你根據方法
                        命名規則命名,出入參數,它在轉換成查詢語句,換句話說,方法對於他來說就是查詢語句,而方法
                        命名規則,就是它給你提供的查詢語句編寫規則,當然這個規則主要是應對複雜多變的條件查詢;
            2.註解方式:
                這個就更加靈活了,它其實就是屏蔽了 底層對於方法名的解釋,直接讀取你方法上的註解的 hql語句
                1. @Query("hql",參數1,參數2) 註解下的方法名可以隨便寫了,參數的順序要和hql順序一致;另外這個
                    只能做查詢,不支持DML語句,就是不支持 增刪改
                2.在 @Query下增加  @Modifying ,另外還要開啓事務,增加@Transactional 
                    默認情況下單元測試時,事務最終會回滾; 可以通過在添加 @Rollback(false) 來阻止回滾;    
              

          4. 有條件的分頁查詢中的 條件的構建:
           public interface Specification<T> {

            /**
            * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
            * {@link Root} and {@link CriteriaQuery}.
            * 
            * @param root  代表的是 T 所代表的類的對象, 目的是爲了調出 T 類的屬性名 比如 'name' 'age' ,
            * @param query   構造簡單條件返回,提供 where 方法;
            * @param cb   構造Predicate 對象,條件對象, 構造複雜查詢效果;
            * @return a {@link Predicate}, must not be {@literal null}.
            */
              Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
            }

 


4.     Spring--->hibernate
    Spring--->SpringDataJPA--->JPA
    這兩個整合的對比分析:
    
    Spring--->hibernate 這個整合中,hibernate做的事情是: 
        1. 封裝了JDBC, 原生JDBC操作步驟較多,按照 hibernate 的配置,我們在DAO中通過繼承 HibernateDaoSupport,
            就直接可以獲得CRUD操作對象 hibernateTemplate;
        2. 封裝了SQL語句, 原生SQL語句操作的對象是數據庫的表,封裝以後我們使用主要使用HQL語句,操作對象是類;
        
    Spring--->SpringDataJPA--->JPA 這個整合中:
        1. JPA的作用和Hibernate作用相同,因爲Hibernate就是JPA的一個實現,所以JPA也可以做兩件事情:
            1. 封裝了JDBC ,
            2. 封裝了SQL語句 ;
            但是,在這個整合中,JPA只做了一件事情,那就是: 1. 封裝了JDBC ,所以它的配置部分與Hibernate幾乎雷同;
            而對於第二件事情:2. 封裝了SQL語句 ; 它交給了另一個框架: SpringDataJPA 來做,我們用一個框架可以做
            的事情,現在我們卻選擇,用兩個框架來完成,那隻能說明一個問題:那就是 JPA 在 1. 封裝了JDBC ,這件事情
            上做得和 Hibernate 不相上下,但是 SpringDataJPA 在 2. 封裝了SQL語句 ;這件事情是相當出色;下面我們
            就來討論一下 SpringDataJPA 對 SQL語句的封裝;
            
        2.    SpringDataJPA 對 SQL語句的封裝: (SimpleJpaRepository 作爲實現類,實際上完成了對SQL語句的封裝)
             封裝原理: SpringDataJPA 它有一個 JPARepository 接口,接口中定義了一些常用的簡單的CRUD操作,
             這個接口有一個默認實現類 SimpleJpaRepository<T, ID extends Serializable>,這個類裏邊實現了
             JPARepository 接口中的方法; 我們寫一個 Dao 接口繼承 JPARepository ,然後將這個接口注入到
             Service 中,這時在Spring做注入操作時,會判斷我們的接口繼承了 JPARepository 然後會 利用 AOP 思想,
             給我們的 Service 注入一個 SimpleJpaRepository 的對象,而這個對象中,它把常用的SQL進行了封裝,極大
             便利了我們常用的存的數據庫操作,比如:
                1. 單個對象數據保存操作,批量對數據保存;
                2. 無條件刪除,無條件查詢操作;
                3. 常用的分頁查詢操作,也做了封裝;
                
            
5.    聊一下 JQueryEasyUI 中數據表 datagrid 的分頁操作:
        DataGrid屬性 中有一個屬性: pagination : true,就開啓了分頁條;
        
        $('#grid').datagrid( {
                    iconCls : 'icon-forward',
                    fit : true,
                    border : false,
                    rownumbers : true,
                    striped : true,
                    pageList: [30,50,100],
                    pagination : true,
                    toolbar : toolbar,
                    url : "../../standard_pageQuery.action",
                    idField : 'id',
                    columns : columns
                });
        
        1. 當我們加載頁面時,會自動傳給服務端兩個數據: 1.當前頁面: page , 2. 每頁顯示記錄條數 rows 
        
        2. datagrid 的url 屬性會根據路徑發送ajax請求, 服務器端會返回json數據:格式如下
            {                                                      
                "total":100,    
                "rows":[ 
                    {"id":"001","name":"10-20公斤","minWeight":"10",
                    "maxWeight":"20","minLength":"11","maxLength":"22",
                    "operator":"張三","operatingTime":"2016-08-18",
                    "company":"杭州分部"}
                ]
            }
            我們不難看出返回的json數據是一個json對象,裏邊有兩個鍵: 
                1. total(記錄總條數) 
                2. rows (記錄內容) 這是一個json數組,數組的元素是json對象.
            就是這樣一種固定格式的 json 數據 grid 獲取以後才能夠正確解析,它會將rows中的對象的 key 和 
            datagrid中的columns 的字段field 的值進行匹配,生成 datagrid (數據表) 中的數據;


6. 下面我們談談 datagrid 中的一個很神奇的方法 load :

     方法名 load   參數 param
    官方API翻譯:  加載和顯示第一頁行。如果指定的param”,它將取代與queryParams 的屬性。通常一個查詢通過一些參數,
            這種方法可以調用從服務器加載新數據。 
        $('#dg').datagrid('load',{
            code: '01',
            name: 'name01'
          }); 
          
    個人理解:就是說你可以用你的 datagrid 對象調用 load 方法,如果沒有傳入 param參數 那麼會發送ajax請求加載第一頁數據
            如果你調用 load 方法時傳入了 param參數,那麼它會作爲請求參數傳到服務器,從服務器加載頁面,那麼這個時候 
            這個param參數我們就可以大作文章了,因爲我們可以通過控制這個param 傳到服務器,控制服務器返回給我們想要的數據;

            
          
        
        
        
        
        
        
        
       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章