【第152期 May 5, 2010】
 

研發新視界

JPA在EJB3.0的應用研究

作者/白淳元

[發表日期:2010/5/5]




前言

JPA是Java Persistence API的縮寫是JSR 220: Enterprise JavaBeans,Version 3.0規範的一部分,是J2EE4中Entity Bean的繼承者,是一個java開發的通用持久化規範Java Persistence API 1.0, 其實就是完全重新定義了的Entity Bean規範。

Java Persistence AP(JPA)可以說是java持久化技術的一個集大成者,它吸取了Hiberante,JDO,TopLink等優秀技術和框架,將這幾年發展成熟起來的基於POJO模型的O/R Mapping技術標準化,成為在J2EE和J2SE環境中通用的java持久化API。值得注意的是Java Persistence API並不是J2EE環境專用,而是在java中的通用API。意味著我們可以在任何需要訪問關聯式資料庫的地方使用JPA,甚至包括swing開發的桌面應用。JPA也不要求一定在J2EE容器中才能運行,而是任何有JVM的環境都可以運用。 這就使得我們可以很容易的把JPA作為一個持久化元件自由的和各種容器/框架(EJB3, Spring等等)組合。

JPA在EJB3.0的應用

於EJB3的環境中使用JPA,我們要先做好JPA的部署。JPA最主要是一個統一的persistence.xml設定檔,可以放到每一個jar的META-INF/目錄下面,也就是說,若是封裝為EJB-JAR,則persistence.xml必須在EJB-JAR根目錄的META-INF資料夾中,以下是筆者所使用persistence.xml的主要內容:



◎persistence-unit:可以有一個或多個,每個persistence-unit定義了持久化內容名稱、使用的資料來源名稱及Hibernate屬性。其中的name屬性用於設置持久化名稱。

◎jta-data-source:用於指定Entity Bean使用的資料來源名稱DefaultMySqlDS,當指定資料來源名稱時java:/是絕對不能缺少,並注意資料來源名稱的大小寫。

◎properties:用於指定Hibernate的各項屬性,在hibernate.hbm2ddl.auto這個標籤的value建議設成none或update,這個標籤的意思是自動對資料庫table進行驗證、建立或更新的動作,有幾種值可參考:

  • validate:對資料庫table進行驗證建立

  • create:對資料庫table進行重新建立,就是會把原有的table刪掉再建一個新的

  • create-drop:對資料庫table進行重新建立,退出時就把table刪掉

  • update:更新資料庫的內容


這次所使用的環境是JBOSS+MYSQL,所以需要在jboss-5.0.0.GA\ server\default\deploy裡面建立一個mysql-ds.xml檔案,若使用的是oracle,則是建立oracle-ds.xml,下面則是筆者所建立的主要內容及一些說明:



jndi-name裡的DefaultMySqlDS是跟persistence.xml裡面的值是相互對應,要特別注意!!

◎connection-url:代表所連結的資料庫位址

◎driver-class:資料庫的驅動為com.mysql.jdbc.Driver

◎user-name:資料庫登入的使用者

◎password:資料庫登入的密碼

為了開發一個與資料庫表對應的Entity Bean,我們首先設計一個使用者user的資料結構,此table共包括3個欄位,如下表:



接下來就是開發一個與該Table對應的Entity Bean,只需要新建一個POJO類,添加3個與table的欄位同名的變數,同時使用一些annotaion符來表示該Entity Bean與table user的對應關係即可。

為此,我們新建一個Entity Bean User.java。我們來看看這個完整的程式碼,如下所示:



Entity Bean通常需要實現Serializable介面,這樣就可以有EJB用戶端創建該物件,並將該物件傳送到Server端,否則將引發java.io.InvalidClassException例外。

該Class是一個Java POJO(Plain Old Java Object) Class,其中包含了3個變數,並為每個變數添加了getter/setter函數。為了將該POJO Class表現為一個實體Bean,添加了一些annotaion符,來與資料表student進行對應,這些annotaion如下。

◎@Entity:指明這是一個Entity Bean,每個Entity Bean對應資料庫中的一個Table。

◎@Table:annotaion的name屬性所對應Table名稱,user Class對應的Table為user。

◎@Column:定義了對應到Column的所有屬性,如Column名是否唯一,是否允許為空,是否允許更新等,其屬性介紹如下。

  • name:映射的列名。如映射user表的name列,如果不指定對應Column名,則會將變數名稱作為預設的對應Column名。

  • unique:是否唯一。

  • nullable:是否允許為空。

  • length:對於字元型列,length屬性指定列的最大字元長度。

  • insertable:是否允許插入。

  • updatable:是否允許更新。

  • columnDefinition:定義建時創建Table此Column的DDL。


◎@Idannotaion:指定Id為Table的Primary Key。

◎@GeneratedValue:定義了標識欄位的生成方式,本例中的Id的值由MySQL資料庫自動生成,它可以有以下多種生成方式。

  • TABLE:資料庫指定用底層的資料Table確保唯一。

  • SEQUENCE:使用資料庫的SEQUENCE 列來保證唯一。

  • IDENTITY:使用資料庫的INDENTIT列來保證唯一。

  • AUTO:資料庫挑選一個合適的方式來保證唯一。

  • NONE:資料庫不負責主鍵的生成,由調用程式來完成。


實作分享

下面我們接著開發一個EntitySessionBean TestDaoBean 實作TestDaoInterFace.java ,並且使用到剛剛所開發的user Entity Bean,來研究其完整程式碼。



@Stateless的Annotation標示出,這是一個Stateless Session Bean不保留任何操作階段的狀態。

EntityManager是實體管理器,顧名思義,它是Entity Bean的管理容器,每個EntityManager會關聯至一個Persistence Context。通過該物件,我們能夠實現與資料庫的各種交互,包括增加、刪減、修改、查詢等。

該實體變數em通過annotaion@PersistenceContext來實現動態注入EntityManager物件,如果persistence.xml檔中配置了多個不同的持久化內容,則還需要指定持久化名稱給EntityManager 物件,可以通過@PersistenceContextannotaion的unitName屬性進行指定,在本例中:

@PersistenceContext(unitName="demo")

em.persist(user);代表我們要透過EntityManager來對TABLE user新增一筆資料,EntityManager還有其它的功能。
em.find();代表查詢。
em.merge();代表更新。
em.remove();代表刪除。
em.contain();檢查是否存在此資料。

最後只要寫個簡單的client端,就可以調用我們上面寫的method了,主要如下:

InitialContext ctx = new InitialContext();
TestDaoInterFace testDaoInterFace = (TestDaoInterFace) ctx.lookup("TestDaoBean/remote");
testDaoInterFace.insertUser("Steve", 28);
System.out.println(testDaoInterFace.getPersonNameByID(1));

如此就可以在資料庫新增一筆user的資料,並且查詢出來了。

這只是最簡單的一對一的映射的例子,由此例子可看到在JPA 中,EJB3的Entity Bean就是一個簡單的java bean,即POJO。不像EJB2中的EntityBean需要跟Container有密切關聯(EJB2中必須有EntityContext),EJB3 中的entityBean和Container無關,事實上在JPA中,EntityBean也不再稱為EntityBean,而是Entity,在EJ3B中和Session Bean/Message Driven Bean已經區別開來。

為了簡化O/R Mapping的配置,JPA大量採用JDK1.5最重要的新特性-annotaion,直接在java代碼中進行配置的標注。採用annotation標注O/R Mapping配置可以大幅度減少以往使用xml配置O/R Mapping工作量,提高效率和可維護性,同時也減少程式碼的產生。