【Hibernate步步為營】--核心對象+持久對象全析(三)

來源:互聯網
上載者:User

標籤:style   blog   class   code   java   c   

       上篇文章討論了Hibernate持久對象的生命週期,在整個生命週期中一個對象會經曆三個狀態,三種狀態的轉換過程在開發過程中是可控的,而且是通過使用方法來控制它們的轉化過程,具體的轉化過程今天就來著重討論下。


二、狀態轉化方法


       前面說到對象之間的轉化過程是通過使用方法來實現的,這些方法是很重要的,先看張圖

     上面這張圖在三篇文章中都有用到,它詳細描述了持久對象三種狀態的轉換過程及具體的轉化方法,另外還有記憶體回收行程,對象在瞬態和脫管狀態下如果長時間不適用將會在某一時刻被Java回收器回收,消亡。


  1、對象直接進入Persistent狀態         

    

     1.1 get方法

         從資料庫中擷取一行資訊,並將該資訊同步到建立的對象中,該方法返回一個Object對象,如果沒有查詢到內容則返回null。下面的執行個體通過採用Session的get方法來擷取一個對象,並將對象轉換為執行個體。

public void testGet1(){Session session=null;Transaction tx = null;try{session=HibernateUtils.getSession();//開啟事務tx= session.beginTransaction();//get載入上來的對象為持久對象//執行get會馬上發出查詢語句,如果不存在會返回nullUser user=(User)session.get(User.class,"ff80808145bc28cc0145bc28ce020002");System.out.println(user.getName());//persistent狀態//persistent狀態的對象,當對象的屬性發生改變的時候//Hibernate在清理緩衝(髒資料檢查)的時候,會和資料庫同步user.setName("趙柳");session.getTransaction().commit();}catch(Exception e){e.printStackTrace();if(tx != null){tx.rollback();}}finally{HibernateUtils.closeSession(session);}}

        設定斷點,擷取User對象。            

              


       擷取到了該對象,通過強制轉換後得到了一個user對象。程式中添加了setName方法,也就是說會更新資料庫中的名稱,執行完成後檢查資料庫,如更新結果。                       

   1.2 load方法

     功能類似於get方法,也是從資料庫中擷取資料並同步到對象中,該方法支援lazy是一種懶漢操作,它返回的是一個持久化的Object對象或者一個代理,所以需要進行轉化。

public void testLoad1(){Session session=null;try{session=HibernateUtils.getSession();//不會馬上查詢語句,因為load支援lazy(消極式載入/懶載入)//什麼教lazy?只有真正使用這個對象的時候,再建立,對於Hibernate來說//才真正發出查詢語句,主要為了提高效能,lazy是Hibernate中非常重要的特性//Hibernate的lazy是如何?的?採用代理對象實現,代理對象主要採用的是CGLIB庫產生的//而不是JDK的動態代理,因為JDK的動態代理只能對實現了借口的類組建代理程式,CGLIB可以對類產生//代理,它採用的是繼承方式User user=(User)session.load(User.class,"8a1b653745bcc7b50145bcc7b7140001");System.out.println(user.getName());//persistent狀態//persistent狀態的對象,當對象的屬性發生改變的時候//Hibernate在清理緩衝(髒資料檢查)的時候,會和資料庫同步user.setName("zhaoliu");session.getTransaction().commit();}catch(Exception e){e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

        查詢擷取該User對象如:

          
        分析,擷取的User對象並不完整,或者說並沒有常見一個User對象,更是一種代理,它使用了CGLIB來預先載入對象,只有在使用該對象時才真正建立。


    1.3 Get Vs load


       get和load方法很重要,在面試Hibernate時經常會考到,下面對比下兩者。
       相同點:(1)功能相同,將關係資料轉化為對象;

                       (2)使用方法相同,同樣需要制定兩個參數
       不同點:(1)load方法支援lazy操作,預先載入對象,在使用時才建立,get是直接將關係資料轉化為對象;

                       (2)load載入對象如果不存在會拋出objectNotFoundException異常,get如果沒有擷取資料會返回null。


  2、手動構造detached對象

        想要擷取對象還有另外一種方法,它區別於get與load方法,是一種手動擷取的方法,首先常見一個對象,然後通過制定id的方式擷取該對象的資料,方法如下:

public void testUer(){Session session=null;try{session=HibernateUtils.getSession();session.beginTransaction();//手動構造detached對象User user=new User();user.setId("8a1b653745bcc7b50145bcc7b7140001");//persistent狀態//persistent狀態的對象,當對象的屬性發生改變的時候//Hibernate在清理緩衝(髒資料檢查)的時候,會和資料庫同步session.getTransaction().commit();}catch(Exception e){e.printStackTrace();}finally{HibernateUtils.closeSession(session);}}

        查看擷取的結果圖:

         
                    
       分析結果圖,代碼中使用了setId方法為該對象制定了id號,在制定id號後就能夠對該對象進行操作,在事務提交後同步到資料庫中,採用了手動指定,手動指定了對象的資訊。

    2.1 Delete方法

       刪除資料庫中指定的對象,在刪除前必須將對象轉化到Persistent狀態,可以使用get、load或者手動的方法指定對象,使用方法如下代碼:

session=HibernateUtils.getSession();session.beginTransaction();User user=(User)session.load(User.class,"8a1b653745bcc6d50145bcc6d67a0001");//建議採用此種方式刪除,先載入再刪除session.delete(user);

   2.2 Update

      更新資料,該方法會修改資料庫中的資料。在使用的時候會出現量中情況,更新資料庫某個欄位值或者更新資料庫的整行值

     2.2.1  更新某個欄位值

      如果只想要更新某個欄位的值,在update前,需要使用load或者get方法使對象轉化為persistent狀態碼如下:

//擷取session對象session=HibernateUtils.getSession();//開啟事務session.beginTransaction();//或者可以使用另外的方法開啟//session.getTransaction().begin();//載入擷取User對象//方法一:使用load方法//User user=(User)session.load(User.class, "8a1b653745bcc7b50145bcc7b7140001");//方法二:手動擷取User user=new User();user.setId("8a1b653745bcc7b50145bcc7b7140001");//更新姓名user.setName("zhangsan");session.update(user);session.getTransaction().commit();

      2.2.2 更新整行                        

      想要更新整行的資料,可以採用手動將狀態轉換到detached狀態,手動指定對象的id值,代碼如下:

//擷取session對象session=HibernateUtils.getSession();//開啟事務session.beginTransaction();//或者可以使用另外的方法開啟//session.getTransaction().begin();//手動擷取User user=new User();user.setId("8a1b653745bcc7b50145bcc7b7140001");//更新姓名user.setName("zhangsan");session.update(user);session.getTransaction().commit();

       查看更新結果:

       
      分析更新結果,它其實更新了資料庫的整行資料,這種更新操作有太多的不確定因素,不建議使用。


   2.3 save方法


        插入資料。在執行save方法時會調用資料庫的insert語句,向資料庫中添加新的一行。save後的對象會轉化為持久態,在此狀態下的對象能夠再次更新對象,在最後提交事務時會同更改更新到資料庫。如下:

public void testSave2(){Session session=null;Transaction tx = null;try{session=HibernateUtils.getSession();//開啟事務tx= session.beginTransaction();//Transient狀態User user=new User();user.setName("zhangsi");user.setPassword("123");user.setCreateTime(new Date());user.setExpireTime(new Date());//persistent狀態//persistent狀態的對象,當對象的屬性發生改變的時候//Hibernate在清理緩衝(髒資料檢查)的時候,會和資料庫同步session.save(user);user.setName("lisi");tx.commit();}catch(Exception e){e.printStackTrace();if(tx != null){tx.rollback();}}finally{HibernateUtils.closeSession(session);}//detached狀態}

查看上例運行結果檢視:

   
        分析結果:session在提交事務的時候其實做了兩部的操作,結合代碼中的更新過程,首先是新增了一個User對象,之後執行了save操作,它會調用insert語句,然後在代碼中做了一個setName的操作,重新修改了名稱,但這時還沒有同步到資料庫中而是在記憶體中,這時就會有兩種狀態,我們稱此時的資料位元髒資料,最後提交事務的時候更新到資料庫中。


結語

       本文針對持久對象的轉化方法展開了詳細的討論,一個對象在整個生命週期中有三種狀態。文章討論至此,核心對象和持久對象的討論已經完成,核心對象構成了Hibernate的內部運行機制,持久對象是關聯式模式和物件模型進行轉化的核心。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.