Sealyu

          --- 博客已遷移至: http://www.sealyu.com/blog

            BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            618 隨筆 :: 87 文章 :: 225 評(píng)論 :: 0 Trackbacks
          原帖地址:http://blog.csdn.net/bq_cui/archive/2007/03/21/1536706.aspx

          開(kāi)始學(xué)習(xí)seam的時(shí)候,有兩個(gè)問(wèn)題:我會(huì)用Spring和Hibernate,但一點(diǎn)也不懂Seam 和EJB3的 EntityManager。我用了一些時(shí)間學(xué)習(xí)seam,但EntityManager 一直困擾我。
              同時(shí)我也有了一些小收獲,愿意跟剛剛開(kāi)始學(xué)習(xí)seam的朋友分享以下。別緊張,我不敢確信我寫(xiě)的東西都正確 ;).
              好了,關(guān)于EntityManager有何用處?它管理你的entities ;)。 那是一些簡(jiǎn)單的java對(duì)象,通過(guò)getters and setters具備一些屬性。這些屬性之一是id(一般是Long數(shù)據(jù)類(lèi)型),并且這些class必須以@Entity注解(annotated )。在seam的源碼中可以找到一大批這樣的例子,例如booking例子。在seam中,一件很重要的事情就是,每個(gè)Entity都有一個(gè) @Name 注解(annotation),這樣,它們才能被注入到其他seam部件(component)中。
              假設(shè)我們有這樣一個(gè)entity class,叫做"Entity"。其生命周期內(nèi)包含以下功能:

          EntityManager 提供了這些功能。首先,如何把EntityManager 引入我的代碼?很簡(jiǎn)單:

          @PersistenceContext
          private EntityManager em;    

              好了,我們看看一個(gè)Entity 進(jìn)程如何產(chǎn)生:

          Entity entity = new Entity();    

              這很簡(jiǎn)單?,F(xiàn)在,這entity 的狀態(tài)是NEW/TRANSIENT 。這意味著一個(gè)entity已經(jīng)存在于你的應(yīng)用程序中,但并不具有id,也不存在于你的數(shù)據(jù)庫(kù)中。

              由于我們要使它持久化(即它應(yīng)被寫(xiě)入數(shù)據(jù)庫(kù)),我們應(yīng)把它的狀態(tài)轉(zhuǎn)換為MANAGED 。

          em.persist(entity);    

              現(xiàn)在,此entity由EntityManager管理了。EntityManager控制entity寫(xiě)入數(shù)據(jù)庫(kù)。這動(dòng)作無(wú)須立刻發(fā)生,可能把你的entity放在cache,稍后寫(xiě)入數(shù)據(jù)庫(kù)。你可以放心,寫(xiě)動(dòng)作肯定會(huì)發(fā)生。

          Ok, what about reading an existing entity from the database? Therefore we use:

          好,如何從數(shù)據(jù)庫(kù)中讀出已存在的entity呢?這樣:

          Entity entity = em.find(Entity.class, Id);    

              每個(gè)entity 有一個(gè)id(我已經(jīng)說(shuō)過(guò),多數(shù)情況下是Long數(shù)據(jù)類(lèi)型),通過(guò)id你可存取entity。這是這里的第二個(gè)參數(shù)。第一個(gè)參數(shù)代表你要存取的Entity class的進(jìn)程。find操作之后,entity的狀態(tài)也是MANAGED 。

          一旦entity數(shù)據(jù)有所改變,將反映到數(shù)據(jù)庫(kù)中。不能確認(rèn)EntityManager何時(shí)會(huì)向數(shù)據(jù)庫(kù)寫(xiě)入更新的數(shù)據(jù)。但是這一事件肯定會(huì)發(fā)生,一般是馬上,但不會(huì)晚于EntityManager消失;)。你可以控制觸發(fā)更新數(shù)據(jù)庫(kù):

          em.flush();    

               這將強(qiáng)制EntityManager 立刻將更新寫(xiě)入數(shù)據(jù)庫(kù)。請(qǐng)記住,這條語(yǔ)句將影響所有狀態(tài)為MANAGED的entitie,而不是當(dāng)前一個(gè)。不過(guò),一般情況下不必這么做。
              如果你想反其道而行之,也就是從數(shù)據(jù)庫(kù)載入一個(gè)entity (因?yàn)閯e人可能已經(jīng)修改其數(shù)據(jù)),這么寫(xiě):
          em.refresh(entity);    

              怎樣刪除一個(gè)entity呢?很簡(jiǎn)單:
          em.remove(entity);    

              現(xiàn)在,entity的狀態(tài)成為REMOVED,表示其已經(jīng)被列入刪除計(jì)劃。你可以用flush()語(yǔ)句,讓刪除動(dòng)作馬上發(fā)生,但沒(méi)必要這么干。

              現(xiàn)在來(lái)點(diǎn)復(fù)雜的。當(dāng)注入EntityManager 的時(shí)候,有一個(gè)事務(wù)范圍持久上下文( Transaction Scoped Persistence Context)。當(dāng)entitie處在MANAGED狀態(tài)時(shí),其處在持久上下文(persistence context )的“容器”中。“事務(wù)范圍”意味什么?首先,什么是“事務(wù)”?

              EJB3Stateful 和 Stateless beans (依同名標(biāo)注辨別)的每個(gè)方法調(diào)用都包裝到一個(gè)事務(wù)內(nèi)。(順便說(shuō)一下,事務(wù)一旦發(fā)生RuntimeException,即發(fā)生會(huì)滾,對(duì)數(shù)據(jù)的改變將撤銷(xiāo))。因此,持久上下文(persistence context)將在調(diào)用方式之前建立,方式調(diào)用結(jié)束后移除。然后,持久上下文中管理的所有entity的狀態(tài)成為 DETACHED。

              假設(shè)在你的bean里頭有兩個(gè)method。第一個(gè)是load(), 它調(diào)用find函數(shù)取出數(shù)據(jù)庫(kù)中的一個(gè)實(shí)體。第二個(gè)是finish(),返回一個(gè)JSF輸出。調(diào)用這兩個(gè)函數(shù)中間修改了實(shí)體數(shù)據(jù)。這種修改持久到數(shù)據(jù)庫(kù)中嗎?回答是:NO。

              load() 函數(shù)結(jié)束后,EntityManager'的持久上下文結(jié)束,它所有管理過(guò)的entity狀態(tài)成為DETACHED。一個(gè)后果是,與新entity相反-有一個(gè)ID,但他們的狀態(tài)并不是managed ,對(duì)這些detached entities 所作的更新并不影響數(shù)據(jù)庫(kù)。如果你想使一個(gè)entity 更新數(shù)據(jù)庫(kù),需要將其重新attach到持久上下文。在這個(gè)例子中,在finish()方法中增加以下行:
          em.merge(entity);    

              現(xiàn)在這個(gè)entity 已經(jīng)合并到finish()方法的持久上下文中(記住,每個(gè)方法是一個(gè)事務(wù),每個(gè)事物有自己的持久上下文),并且狀態(tài)是又變?yōu)閙anaged。

               這樣做是可以的,但有兩個(gè)缺點(diǎn):
          -需要調(diào)用merge(->多了一些代碼)
          -調(diào)用find()之前,如果某個(gè)entity未初始化,而你又要存取它的某些屬性,將會(huì)得到exception 錯(cuò)誤。

              有一個(gè)簡(jiǎn)單的解決方案:擴(kuò)展持久上下文的生命期,這樣,當(dāng)調(diào)用多個(gè)事務(wù)/方法時(shí),entity狀態(tài)始終保持為managed 。因此,我們改變EntityManager的注入方式:
          @PersistenceContext(type=PersistenceContextType.EXTENDED
          private EntityManager em;   

               現(xiàn)在,managed entities "生活在"一個(gè)擴(kuò)展持久上下文中( Extended Persistence Context )。

              你甚至無(wú)須呼叫merge()方法,因?yàn)閑itities從未被DETACHED。你可能會(huì)問(wèn):普通事務(wù)范圍( "normal" (transaction scoped) )持久上下文的好處是什么?它一直依附于你做的事情(小崔:什么意思?)。擴(kuò)展上下文需要更多的內(nèi)存,因?yàn)榧词鼓悴恍枰惨恢贝嬖谟趦?nèi)存。并且一旦entities被其他的bean改變(它們有自己的持久上下文),你需要顯式地調(diào)用refresh()方法(在overviews/list頁(yè)面)。當(dāng)你需要普通EntityManager 時(shí)它就在那里,因其生命周期短,只能操作即時(shí)數(shù)據(jù);)
             
              當(dāng)談及列表:為取得不止一個(gè)實(shí)體,而是一個(gè)實(shí)體集合,使用:
          List<Entity> entities = em.createQuery("from Entity").getResultList();    

              這不是“真正”SQL,而是類(lèi)似sql的東西,稱(chēng)之為EJBQL。你可以用它執(zhí)行某些條件查詢(xún),排序等,如
          ..."from Entity where lastName=".nameToSearchFor." order by firstName"    

              僅使用entity屬性名稱(chēng)即可。關(guān)于EJBQL 要說(shuō)的太多了,但對(duì)于本篇介紹來(lái)說(shuō)這已足夠。

              好,基本介紹到此為止。希望對(duì)你來(lái)說(shuō),在如何使用EntityManager方面,這一個(gè)簡(jiǎn)單易懂的介紹。

              我已聲明過(guò),不能保證百分百正確。并且肯定有許多英語(yǔ)語(yǔ)法錯(cuò)誤(對(duì)不起,我是德國(guó)人,不要打我PP噢)。歡迎斧正。


          2007.4.11翻譯自:
          http://www.jboss.com/index.html?module=bb&op=viewtopic&t=88460

          posted on 2009-04-13 15:34 seal 閱讀(2019) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Seam
          主站蜘蛛池模板: 宜城市| 永胜县| 福鼎市| 米脂县| 乌鲁木齐县| 泰顺县| 邻水| 宝山区| 尚义县| 宁德市| 桃源县| 定日县| 渭源县| 宣化县| 泰来县| 铜山县| 丰城市| 舞钢市| 波密县| 定安县| 井研县| 南城县| 辽源市| 甘肃省| 望谟县| 佛山市| 高邮市| 平罗县| 聊城市| 周宁县| 楚雄市| 垦利县| 夏河县| 西华县| 罗甸县| 同德县| 扎赉特旗| 鄢陵县| 盐边县| 隆子县| 天气|