丄諦啲仇魜ヤ
          如 果 敵 人 讓 你 生 氣 , 那 說 明 你 沒 有 勝 他 的 把 握!
          posts - 6,comments - 56,trackbacks - 1
          持久化層的Java對象可處于哪些狀態(tài)?這些狀態(tài)有哪些特征?

          選自<<精通Hibernate:Java對象持久化技術(shù)詳解>> 作者:孫衛(wèi)琴 來源:www.javathinker.org

          當(dāng)應(yīng)用程序通過new語句創(chuàng)建了一個對象,這個對象的生命周期就開始了,當(dāng)不再有任何引用變量引用它,這個對象就結(jié)束生命周期,它占用的內(nèi)存就可以被JVM的垃圾回收器回收。對于需要被持久化的Java對象,在它的生命周期中,可處于以下三個狀態(tài)之一:

          (1) 臨時狀態(tài)(transient):剛剛用new語句創(chuàng)建,還沒有被持久化,不處于Session的緩存中。處于臨時狀態(tài)的Java對象被稱為臨時對象。
          (2) 持久化狀態(tài)(persistent):已經(jīng)被持久化,加入到Session的緩存中。處于持久化狀態(tài)的Java對象被稱為持久化對象。
          (3) 游離狀態(tài)(detached):已經(jīng)被持久化,但不再處于Session的緩存中。處于游離狀態(tài)的Java對象被稱為游離對象。

          圖1為Java對象的完整狀態(tài)轉(zhuǎn)換圖,Session的特定方法觸發(fā)Java對象由一個狀態(tài)轉(zhuǎn)換到另一個狀態(tài)。從圖1看出,當(dāng)Java對象處于臨時狀態(tài)或游離狀態(tài),只要不被任何變量引用,就會結(jié)束生命周期,它占用的內(nèi)存就可以被JVM的垃圾回收器回收;當(dāng)處于持久化狀態(tài),由于Session的緩存會引用它,因此它始終處于生命周期中。


          臨時對象的特征

          臨時對象具有以下特征:
          (1) 不處于Session的緩存中,也可以說,不被任何一個Session實(shí)例關(guān)聯(lián)。
          (2) 在數(shù)據(jù)庫中沒有對應(yīng)的記錄。

          在以下情況下,Java對象進(jìn)入臨時狀態(tài):
          (1) 當(dāng)通過new語句剛創(chuàng)建了一個Java對象,它處于臨時狀態(tài),此時不和數(shù)據(jù)庫中的任何記錄對應(yīng)。
          (2) Session的delete()方法能使一個持久化對象或游離對象轉(zhuǎn)變?yōu)榕R時對象。對于游離對象,delete()方法從數(shù)據(jù)庫中刪除與它對應(yīng)的記錄;對于持久化對象,delete()方法從數(shù)據(jù)庫中刪除與它對應(yīng)的記錄,并且把它從Session的緩存中刪除。

          持久化對象的特征

          持久化對象具有以下特征:
          (1) 位于一個Session實(shí)例的緩存中,也可以說,持久化對象總是被一個Session實(shí)例關(guān)聯(lián)。
          (2) 持久化對象和數(shù)據(jù)庫中的相關(guān)記錄對應(yīng)。
          (3) Session在清理緩存時,會根據(jù)持久化對象的屬性變化,來同步更新數(shù)據(jù)庫。

          Session的許多方法都能夠觸發(fā)Java對象進(jìn)入持久化狀態(tài):
          (1) Session的save()方法把臨時對象轉(zhuǎn)變?yōu)槌志没瘜ο蟆?br /> (2) Session的load()或get()方法返回的對象總是處于持久化狀態(tài)。
          (3) Session的find()方法返回的List集合中存放的都是持久化對象。
          (4) Session的update()、saveOrUpdate()和lock()方法使游離對象轉(zhuǎn)變?yōu)槌志没瘜ο蟆?nate注:根據(jù)hibernate reference的說法當(dāng)試圖用update更新一個持久化對象時會拋異常)
          (5)當(dāng)一個持久化對象關(guān)聯(lián)一個臨時對象,在允許級聯(lián)保存的情況下,Session在清理緩存時會把這個臨時對象也轉(zhuǎn)變?yōu)槌志没瘜ο蟆?

          Hibernate保證在同一個Session實(shí)例的緩存中,數(shù)據(jù)庫表中的每條記錄只對應(yīng)惟一的持久化對象。例如對于以下代碼,共創(chuàng)建了兩個Session實(shí)例:session1和session2。session1和session2擁有各自的緩存。在session1的緩存中,只會有惟一的OID為1的Customer持久化對象,在session2的緩存中,也只會有惟一的OID為1的Customer持久化對象。因此在內(nèi)存中共有兩個Customer持久化對象,一個屬于session1的緩存,一個屬于session2的緩存。引用變量a和b都引用session1緩存中的Customer持久化對象,而引用變量c引用session2緩存中的Customer持久化對象:

          Session session1=sessionFactory.openSession();
          Session session2=sessionFactory.openSession();
          Transaction tx1 = session1.beginTransaction();
          Transaction tx2 = session2.beginTransaction();

          Customer a=(Customer)session1.load(Customer.class,new Long(1));
          Customer b=(Customer)session1.load(Customer.class,new Long(1));
          Customer c=(Customer)session2.load(Customer.class,new Long(1));

          System.out.println(a= =b); //true
          System.out.println(a= =c); //false

          tx1.commit();
          tx2.commit();
          session1.close();
          session2.close();

          Java對象的持久化狀態(tài)是相對于某個具體的Session實(shí)例的,以下代碼試圖使一個Java對象同時被兩個Session實(shí)例關(guān)聯(lián):

          Session session1=sessionFactory.openSession();
          Session session2=sessionFactory.openSession();
          Transaction tx1 = session1.beginTransaction();
          Transaction tx2 = session2.beginTransaction();

          Customer c=(Customer)session1.load(Customer.class,new Long(1)); //Customer對象被session1關(guān)聯(lián)
          session2.update(c); //Customer對象被session2關(guān)聯(lián)
          c.setName("Jack"); //修改Customer對象的屬性

          tx1.commit(); //執(zhí)行update語句
          tx2.commit(); //執(zhí)行update語句
          session1.close();
          session2.close();

          當(dāng)執(zhí)行session1的load()方法時,OID為1的Customer對象被加入到session1的緩存中,因此它是session1的持久化對象,此時它還沒有被session2關(guān)聯(lián),因此相對于session2,它處于游離狀態(tài)。當(dāng)執(zhí)行session2的update()方法時,Customer對象被加入到session2的緩存中,因此也成為session2的持久化對象。接下來修改Customer對象的name屬性,會導(dǎo)致兩個Session實(shí)例在清理各自的緩存時,都執(zhí)行相同的update語句:

          update CUSTOMERS set NAME='Jack' …… where ID=1;
          在實(shí)際應(yīng)用程序中,應(yīng)該避免一個Java對象同時被多個Session實(shí)例關(guān)聯(lián),因?yàn)檫@會導(dǎo)致重復(fù)執(zhí)行SQL語句,并且極容易出現(xiàn)一些并發(fā)問題。

          posted on 2007-09-17 20:33 Crying 閱讀(579) 評論(0)  編輯  收藏 所屬分類: hibernate
          主站蜘蛛池模板: 曲靖市| 靖江市| 莆田市| 贵州省| 营山县| 高雄县| 德保县| 岫岩| 灌南县| 双桥区| 兴义市| 大足县| 桂林市| 什邡市| 云南省| 定日县| 米泉市| 长治市| 阿拉善右旗| 白玉县| 蓝山县| 金寨县| 霍邱县| 息烽县| 化德县| 威远县| 东城区| 台山市| 黔西| 息烽县| 呼伦贝尔市| 伊宁市| 建瓯市| 噶尔县| 富川| 金华市| 祁东县| 宾阳县| 象州县| 神木县| 北辰区|