love fish大鵬一曰同風起,扶搖直上九萬里

          導航

          <2006年7月>
          2526272829301
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          公告

          留言簿(15)

          隨筆分類(493)

          隨筆檔案(498)

          相冊

          閱讀排行榜

          常用鏈接

          統計

          積分與排名

          friends

          link

          最新評論

          EJB3.0之操作Entity

          操作持久化Entity

          對Entity進行操作的API都設計在javax.persistence.EntityManager接口上。EntityManager,顧名思義是管理所有EJB 3運行環境中的所有Entity。 EntityManager根據運行的環境不同分為容器管理的EntityManager和應用管理的EntityManager。Liberator EJB3是一個可以運行在J2SE環境中的 嵌入式的EJB3 Persistence實現,因此在Liberator EJB3中的 EntityManager都是指應用管理的EntityManager。

          配置和獲得EntityManager

          在J2SE環境中,EJB3定義了一個javax.persistence.Persistence類用于啟動EJB3運行環境。要獲得EntityManager,首先需要通過javax.persistence.Persistence獲得EntityManagerFactory,然后調用EntityManagerFactory.createEntityManager()方法獲得。
                          
              // 獲得默認當前的EntityManagerFactory                
              final EntityManagerFactory emf = Persistence.createEntityManagerFactory();
              final EntityManager entityManager = emf.createEntityManager();    
                          
                      

          當調用Persistence.createEntityManagerFactory()的時候,Persistence會做以下的步驟:

          • 搜索當前jar包的META-INFO/persistence.xml配置文件
          • 如果沒有在META-INFO下找到persistence.xml,搜索當前線程的ContextClassLoader中的persistence.xml
          • 根據獲得的persistence.xml初始化EntityManagerFactory
          每個EntityManagerFactory都必須有一個persistence.xml配置文件。下面是一個例子:
                          
          <entity-manager>
              <name>myEntityManager</name>
              <provider>com.redsoft.ejb3.PersistenceProviderImpl</provider>
              <class>com.redsoft.samples.HelloEntityBean</class>
              <properties>
                  <property name="ConnectionDriverName" value="com.mysql.jdbc.Driver"/>
                  <property name="ConnectionURL" value="jdbc:mysql://localhost/EJB3Test"/>
                  <property name="ConnectionUserName" value="ejb3"/>
                  <property name="ConnectionPassword" value="ejb3"/>
                  <property name="RetainValues" value="true"/>
                  <property name="RestoreValues" value="false"/>
                  <property name="IgnoreCache" value="false"/>
                  <property name="NontransactionalRead" value="true"/>
                  <property name="NontransactionalWrite" value="false"/>
                  <property name="Multithreaded" value="false"/>
                  <property name="Liberator.option.action" value="create"/>
                  <property name="Liberator.option.cache" value="com.redsoft.jdo.enterprise.OscacheAdapter"/>
                  <property name="Liberator.option.JMXEnabled" value="false"/>
                  <property name="Liberator.option.NamingPort" value="3012"/>
                  <property name="Liberator.option.JMXPort" value="3011"/>
                  <property name="Liberator.option.JDBC.scrollable" value="false"/>
                  <property name="Liberator.option.JDBC.fetchSize" value="500"/>
                  <property name="cache.algorithm" value="LRUCache"/>
                  <property name="cache.capacity" value="5000"/>
                  <property name="log4j.logger.com.redsoft" value="FATAL"/>
              </properties>
          </entity-manager>   
                          
                      

          <name></name> 定義一個EntityManagerFactory的名字,這樣當應用中需要多個EntityManagerFactory的時候可以區別。通常情況下,一個EntityManagerFactory對應一個數據源。

          <provider></provider> 定義采用的什么EJB3 Persistence運行環境(也就是EJB3 Persistence產品),例子中采用的的是Liberator EJB3的運行環境。正如前面說的,在EJB3規范中, EJB3 Persistence運行環境( Runtime )是作為一個獨立的嵌入式模塊,你可以隨意的更換不同的EJB3 Persistence運行環境而不會影響你的應用程序。甚至在J2EE服務器內運行你也可以不用服務器本身提供的EJB3 Persistence運行環境,而采用第三方的EJB3 Persistence運行環境

          <class></class> 定義哪些類是Entity持久化類。如果是測試環境或者你不采用ear/war的方式發布你的應用,而只是把編譯后的類直接拷貝到web容器中,在添加一個新的Entity類時,需要在這里添加一行。要求這個步驟是因為在J2EE 5架構中EJB3運行環境的嵌入式設計。采用這種松耦合設計使EJB3 Persistence運行環境不能控制持久化類的加載(由J2EE服務器負責加載), 這樣EJB3 Persistence運行環境就無法分辨jvm中哪個類是持久化Entity類,哪個不是。因此需要一個額外的信息來讓EJB3 Persistence知道那些是持久化Entity。

          <property></property> 定義了了EJB3 Persistence運行環境需要的其他參數,這些參數不是標準的,而是由EJB3 Persistence運行環境的廠商自行定義。

          詳細的配置方法參看persistence.xml的語法。

          Entity的生命周期和狀態

          在EJB3中定義了四種Entity的狀態:
          • 新實體(new)。Entity由應用產生,和EJB3 Persistence運行環境沒有聯系,也沒有唯一的標示符(Identity)。
          • 持久化實體(managed)。新實體和EJB3 Persistence運行環境產生關聯(通過persist(), merge()等方法),在EJB3 Persistence運行環境中存在和被管理,標志是在EJB3 Persistence運行環境中有一個唯一的標示(Identity)。
          • 分離的實體(detached)。Entity有唯一標示符,但它的標示符不被EJB3 Persistence運行環境管理, 同樣的該Entity也不被EJB3 Persistence運行環境管理。
          • 刪除的實體(removed)。Entity被remove()方法刪除,對應的紀錄將會在當前事務提交的時候從數據庫中刪除。

          持久化Entity(Persist)

                          
              final EntityManagerFactory emf = Persistence.createEntityManagerFactory();
              final EntityManager entityManager = emf.createEntityManager();
          
              final HelloEntityBean hello = new HelloEntityBean( 1, "foo" );
              EntityTransaction trans = entityManager.getTransaction();
              trans.begin();
              
              // 持久化hello,在此操作之前hello的狀態為new
              entityManager.persist( hello );
              
              // 這時hello的狀態變為managed
              
              trans.commit();
          
              entityManager.close();
              
              // 這時hellow的狀態變為detached.
              
                           
                      
          Liberator EJB3支持Persistence by reachability。當保存一個Entity時,以該對象為根對象的整個對象圖都會自動的被保存。但在EJB3中,我們仍然可以通過關系元數據(比如OneToOne,OneToMany)的cascade屬性來精確定義保存的級聯行為。 下面我們來看看不同的cascade屬性的區別。

          不配置cascade的情況下,EJB3 Persistence運行環境默認不會采用Persistence by reachability。

                          
              public class Father{
                  @Id
                  int id
                  
                  String name;
                  
                  // OneToOne沒有配置cascade屬性,因此默認不會使用Persistence by reachablity
                  @OneToOne
                  Son mySon
                  
                  public Father( int id, String name, Son mySon ){
                      this.id = id;
                      this.name = name;
                      this.mySon = mySon;
                  }
              }
                            
          現在來保存一個Father和Son。
                          
              final EntityManager manager = emf.createEntityManager();
              manager.getTransaction().begin;
              
              Son mySon = new Son();
              Father = new Father( 1, "father" mySon );
              
              // 保存Father
              manager.persist( father );
              
              // 由于OneToOne關系中沒有配置casacade屬性,father 關聯的mySon不會被自動保存,需要分別保存
              manager.persist( mySon );
              manager.getTransaction().commit();
              manager.close();
                           
          現在我們配置casacde=CascadeType.ALL
                          
              public class Father{
                  @Id
                  int id
                  
                  String name;
                  
                  // OneToOne配置cascade=CascadeType.ALL,配置cascade=CascadeType.PERSIT也對persist操作也可以獲得同樣的效果。
                  // CascadeType.ALL包含CascadeType.PERSIST。
                  @OneToOne(cascade=CascadeType.ALL)
                  Son mySon
                  
                  public Father( int id, String name, Son mySon ){
                      this.id = id;
                      this.mySon = mySon;
                      this.name = name;
                  }
              }
                            
          在代碼中同樣持久化Father和mySon。
                          
              final EntityManager manager = emf.createEntityManager();
              manager.getTransaction().begin;
              
              Son mySon = new Son();
              Father = new Father( 1, mySon );
              
              // 保存Father。由于OneToOne關系中配置casacade=CascadeType.ALL屬性,關聯的mySon會自動地被持久化
              manager.persist( father );
              manager.getTransaction().commit();
              manager.close();
                           
          由于Liberator EJB3運行環境采用了弱引用POJO管理技術,能很好的支持Persistence by reachablity而不會有其他產品有的潛在內存回收的問題, 因此建議在應用中盡可能使用cascade=CascadeType.ALL來減少持久化操作的復雜性和代碼量,特別是在有復雜對象關系圖的時候。

          獲取Entity

          如果知道Entity的唯一標示符,我們可以用find()方法來獲得Entity。
                                  
              Father father = manager.find( Father.class, new Integer( 1 ) );
                      
              // 由于JDK1.5支持自動轉型,也可以如下使用
                      
              Father father = manager.find( Father.class, 1 );
              
              /* 
              * 或者,可以用Entity名字作為查找。但無法利用JDK 1.5的自動轉型功能,
              *  需要使用對象作為查找主鍵,并需要對獲得Entity進行轉型
              */
              
              Father father = (Father)manager.find( "com.redsoft.samples.Father", new Integer( 1 ) );
                      
                    

          更新Entity

          對Entity的更新必須在事物內完成。和persist中一樣,關系元數據的cascade屬性對是否集聯刪除有影響。
                          
              transaction.begin();                
              Father father = manager.find( Father.class, 1 );
              
              // 更新原始數據類型
              father.setName( "newName" );
              
              // 更新對象引用
              Son newSon = new Son();
              father.setSon( newSon );
              
              
              // 提交事務,剛才的更新同步到數據庫
              transaction.commit();
                           

          刪除Entity

          對Entity的刪除必須在事物內完成。
                          
              transaction.begin();                
              
              Father father = manager.find( Father.class, 1 );
                  
              // 如果father/son的@OneToOne的cascade=CascadeType.ALL,在刪除father時候,也會把son刪除。
              // 把cascade屬性設為cascade=CascadeType.REMOVE有同樣的效果。
              manager.remove( father );
                  
              // 提交事務,剛才的更新同步到數據庫
              transaction.commit();
                           

          脫離/附合(Detach/Merge)

          在三層或者分布式應用中,我們很多時候需要Entity能脫離EntityManager,避免長時間保持EntityManager打開占用資源和可以在不同的JVM之間傳遞Entity。

          在脫離EJB3 Persistence Runtime(EntityManager)的管理后,我們仍然可以讀取或者修改Entity中的內容。而在稍后的時間,我們又可以將Entity重新和原有或者新的EntityManager附合,如果附合前Entity被改動過,更改的數據可以自動的被發現并和數據庫同步。

                          
              EntityManager entityManager = emf.createEntityManager();
              
              // 這時Father還是被EntityManager管理的
              Father father = manager.find( Father.class, 1 );
              
              // 當entityManger關閉的時候,當前被entityManager管理的Entity都會自動的脫離EntityManager,狀態轉變為detached
              entityManager.close();
              
              // 脫離EntityManager后,我們仍然可以修改Father的屬性
              father.setName( "newName" );
              
              // 在稍后的,我們可以將father重新附和到一個新的或者原來的EntityManager中
              EntityManager newEntityManager = emf.createEntityManager();
              
              // 附合( merge )需要在事務中進行
              newEntityManager.getTransaction().begin();
              newEntityManager.merge( father );
              
              // commit后father中的被修改的內容會同步到數據庫。
              newEntityManager.getTransaction().commit();
              
          
                           

          Liberator EJB3 Persistnece運行環境由于支持Persistence-by-reachablity。我們建議采用cascade=CascadeType.ALL,這樣當需要附合的是一個對象圖的時候,我們只需要merge根對象即可,整個對象圖,對象圖中被修改過的對象都會被自動識別和同步。

          需要注意的是在脫離EJB3 Persistence Runtime的管理后,如果對象中有定義為lazy-load的屬性將無法訪問。

          posted on 2006-07-03 00:57 liaojiyong 閱讀(1152) 評論(0)  編輯  收藏 所屬分類: EJB

          主站蜘蛛池模板: 秦安县| 南澳县| 葫芦岛市| 枝江市| 于田县| 淮安市| 康马县| 彰化市| 大同市| 沈阳市| 伊宁县| 綦江县| 漳州市| 阳城县| 嘉峪关市| 凤山县| 涟水县| 南川市| 柏乡县| 方城县| 潮州市| 阜新市| 大姚县| 台北市| 金乡县| 盐亭县| 布尔津县| 舒兰市| 依安县| 舞阳县| 通海县| 泽库县| 安顺市| 元阳县| 宜州市| 平舆县| 通榆县| 江阴市| 靖远县| 桑植县| 西华县|