Eclipse+Jboss快速上手EJB -- 2. 設計一個實體Bean
????這個系列文章我是根據 Rick Hightower 發表在 IBM 網站的文章 《EJB - CMP/CMR 介紹》 改編而成的,看這篇文章前一定要參考一下,這樣理解起來很方便。關于 CMP 方面的知識我不說了,我這里只是介紹如何使用 Lomboz 和 JBoss-IDE 在Eclipse 中開發 CMP。
?
??? 在看這篇文章之前,需要對開發環境的配置了解清楚,這一點我在前篇文章《Eclipse快速上手EJB -- 1. Lomboz + JBoss-IDE 配置1+2 》?中已經詳細介紹了,這篇文章就是以它為前提進行的。
?
一、JBoss相關配置
?
??
?? 在?《快速上手 MySQL --圖形化操作詳解?》 中談到的mysql-connector-java-3.0.16-ga.zip現在有了用場,將其解壓,會發現其中有一個文件 mysql-connector-java-3.0.16-ga-bin.jar,它就是 MySQL的驅動程序。把它復制到F:\java\jboss\server\default\lib 目錄下,這里 F:\java\jboss 是JBoss的安裝目錄。
?
從jboss\docs\examples\jca\目錄下復制mysql-ds.xml文件到jboss\server\default\deploy目錄,需要做一點修改。
mysql-ds.xml
<?
xml
version="1.0" encoding="UTF-8"?>
<!--$Id: mysql-ds.xml,v 1.3 2004/09/15 14:37:40 loubyansky Exp $-->
<!--? Datasource config for MySQL using 3.0.9 available from:
http://www.mysql.com/downloads/api-jdbc-stable.html
-->
<datasources>
? <local-tx-datasource>
??? <jndi-name>MySqlDS</jndi-name>
??? <connection-url>jdbc:mysql://localhost:3306/cmp_sample?useUnicode=true&characterEncoding=GBK</connection-url>
??? <driver-class>com.mysql.jdbc.Driver</driver-class>
??? <user-name>root</user-name>
??? <password>javamxj</password>
????? <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
????? <metadata>
???????? <type-mapping>mySQL</type-mapping>
????? </metadata>
? </local-tx-datasource>
</datasources>
?
<!--$Id: mysql-ds.xml,v 1.3 2004/09/15 14:37:40 loubyansky Exp $-->
<!--? Datasource config for MySQL using 3.0.9 available from:
http://www.mysql.com/downloads/api-jdbc-stable.html
-->
<datasources>
? <local-tx-datasource>
??? <jndi-name>MySqlDS</jndi-name>
??? <connection-url>jdbc:mysql://localhost:3306/cmp_sample?useUnicode=true&characterEncoding=GBK</connection-url>
??? <driver-class>com.mysql.jdbc.Driver</driver-class>
??? <user-name>root</user-name>
??? <password>javamxj</password>
????? <!-- corresponding type-mapping in the standardjbosscmp-jdbc.xml (optional) -->
????? <metadata>
???????? <type-mapping>mySQL</type-mapping>
????? </metadata>
? </local-tx-datasource>
</datasources>
?
??? 這是修改后的文件,很簡單,注意用戶名和密碼替換成自己的,還有就是使用的數據庫是“cmp_sample”,如果沒有這個數據庫,那么先在MySQL中建立它。使用GBK進行編碼,解決了中文問題(結合《快速上手 MySQL --圖形化操作詳解?》中 MySQL 的配置)。
?
?
?
二、建立項目
?
?
●?
新建一個 Lomboz J2EE Project:
·
項目名:CMP_Sample??
·
EJB Modules:cmpEJB
·
Targeted Server:? JBoss 4.0.0
?
●??
繼續在 CMP_Sample 項目中,右擊“src” ->新建 ->Lomboz EJB Creation Wizard :
·
?包(K) :javamxj.ejb.cmp
·
?名稱(M): User
·
?EJB Type:?選擇?Container?Managed Entity?EJB
?? 點擊下一步。

?
●
同樣,再增加一個密碼欄:
·
?Field: password,
·
Field Type: java.lang.String,
·
Database Column: 密碼,
·
SQL Type: varchar
? 這個不要使它成為主鍵。
? 最后點擊完成。
?
?
三、驗證配置
?
·
現在修改生成的 UserBean.java 文件,先添加自動創建表的語句

?
·
注意:如果使用自動創建表的語句,這里有個bug:

?
?
●?
好了,現在來試驗一下各種配置有沒有問題:
?
·
先將 UserBean.java 添加到 cmpEJB 模塊中,然后 lomboz ->Generate EJB Classes 生成其它ejb類文件(建議看看生成的文件,弄清楚 XDoclet 的原理)。
?
·
運行 MySQl 服務,再通過 Lomboz?啟動 JBoss 服務器。
?
·
然后通過 Deploy Module? 部署 cmpEJB 模塊,再打開MySql的客戶端,會發現在 cmp_sample 數據庫中已經自動生成了一個 usertable 的數據表,如圖:

如果能順利進行到這一步,那么各種配置都沒問題,再開始下一階段。
?
?
●
完成 ejbCreate 和 ejbPostCreate 方法:

?
●
在上面的 @ejb.bean 中添加? view-type = "local"?

?
保存,UserBean 暫時告一段落。
?
?
四、創建會話Bean
?
●
右擊 javamxj.ejb.cmp包,還是選擇Lomboz EJB Creation Wizard :
·
?包(K) :javamxj.ejb.cmp
·
?名稱(M): UserManagement
·
?EJB Type:?選擇?Stateless
然后,點擊“完成”,這時會生成一個 UserManagementBean.java 的文件
?
●
首先,增加一個 UserLocalHome 的變量 userHome,
? private UserLocalHome userHome = null;
?
●
然后右擊 UserManagementBean ->J2EE ->Add?Create Method(這是 JBossv-IDE 附帶的):

?
?
●
下一步:

在生成的代碼框中添加語句:
userHome = UserUtil.getLocalHome();
?
●
如下圖:需要手工輸入的語句已經標出來了:

?
?
?
●?
?添加業務方法:
?
· 增加 addUser 方法,
向上面操作一樣,右擊 UserManagementBean ->J2EE ->Add?Business Method:

在生成的代碼框中添加語句:
UserLocal user = userHome.create(email, password);
?
· 增加 removeUser 方法

在生成的代碼框中添加語句:
userHome.remove(email);
?
· 增加?verifyPassword 方法

在生成的代碼框中添加語句:
UserLocal user = userHome.findByPrimaryKey(email);
return user.getPassword().equals(password);
return user.getPassword().equals(password);
?
?
●?
為了將 UserBean 與 UserManagementBean 聯系起來,在上面注釋中添加:
?*?????????? view-type = "remote"
?* @ejb.ejb-ref ejb-name = "User"
?*??? view-type = "local"
?*??? ref-name = "ejb/UserLocal"?
?*
?*?? @jboss.ejb-local-ref ref-name = "UserLocal"?
?*???? jndi-name = "UserLocal"
?*??? view-type = "local"
?*??? ref-name = "ejb/UserLocal"?
?*
?*?? @jboss.ejb-local-ref ref-name = "UserLocal"?
?*???? jndi-name = "UserLocal"
如圖:

?
? 好了,UserManagementBean 暫時完成了。
?
●
?將 UserManagementBean 加入到 cmpEJB 模塊中,
?
·
??然后 lomboz ->Generate EJB Classes
?
·
運行 MySQl 服務,再通過 Lomboz?啟動 JBoss 服務器。
?
·
然后通過 Deploy Module? 部署 cmpEJB 模塊
?
? 如果一切正常,那么開始創建客戶端。
?
?
?
五、創建客戶端
?
·
右擊 src?文件夾 ->新建 ->Lomboz EJB Test Client? Wizard:

?
· 修改生成的 CMPClient1.java

?
· 運行客戶端程序,則客戶端控制臺會輸出:Login =true
?
· 同時,用 MySQL 客戶端軟件查看 cmp_sample 表,則如下,顯示3條數據。

?
?
?
六、完整的源碼
?
UserBean.java
/* * 創建日期 2005-1-14 * * 作者:javamxj(分享java快樂) */ package javamxj . ejb . cmp ; /** * * <! - - begin - user - doc - - > You can insert your documentation for ' <em> <b> UserBean </b> </em> '. <! - - end - user - doc - - > * <! - - begin - lomboz - definition - - > <?xml version=" 1.0 " encoding="UTF - 8 "?> <lomboz : EJB xmlns : j2ee=" http://java.sun.com/xml/ns/j2ee " xmlns : lomboz=" http://lomboz.objectlearn.com/xml/lomboz "> <lomboz : entity> <lomboz : entityEjb> <j2ee : display - name>User< / j2ee : display - name> <j2ee : ejb - name>User< / j2ee : ejb - name> <j2ee : ejb - class>javamxj . ejb . cmp . UserBean< / j2ee : ejb - class> <j2ee : persistence - type>Container< / j2ee : persistence - type> <j2ee : prim - key - class>java . lang . String< / j2ee : prim - key - class> <j2ee : cmp - version> 2. x< / j2ee : cmp - version> <j2ee : abstract - schema - name>userSchema< / j2ee : abstract - schema - name> <j2ee : primkey - field>eamil< / j2ee : primkey - field> < / lomboz : entityEjb> <lomboz : fieldMappings> <lomboz : fieldName>email< / lomboz : fieldName> <lomboz : fieldType>java . lang . String< / lomboz : fieldType> <lomboz : columnName>電子郵件< / lomboz : columnName> <lomboz : jdbcType>VARCHAR< / lomboz : jdbcType> <lomboz : sqlType>varchar< / lomboz : sqlType> <lomboz : readOnly>false< / lomboz : readOnly> <lomboz : primaryKey>true< / lomboz : primaryKey> < / lomboz : fieldMappings> <lomboz : fieldMappings> <lomboz : fieldName>password< / lomboz : fieldName> <lomboz : fieldType>java . lang . String< / lomboz : fieldType> <lomboz : columnName>密碼< / lomboz : columnName> <lomboz : jdbcType>VARCHAR< / lomboz : jdbcType> <lomboz : sqlType>varchar< / lomboz : sqlType> <lomboz : readOnly>false< / lomboz : readOnly> <lomboz : primaryKey>false< / lomboz : primaryKey> < / lomboz : fieldMappings> <lomboz : tableName>userTable< / lomboz : tableName> <lomboz : dataSourceName>< / lomboz : dataSourceName> < / lomboz : entity> < / lomboz : EJB> <! - - end - lomboz - definition - - > * * <! - - begin - xdoclet - definition - - > * @ ejb . bean name="User" * jndi - name="User" * type="CMP" * primkey - field="email" * schema="userSchema" * cmp - version=" 2. x" * view - type = "local" * data - source="" * * @ ejb . persistence * table - name="userTable" * * @ ejb . finder * query="SELECT OBJECT(a) FROM userSchema as a" * signature="java . util . Collection findAll()" * * @ jboss . persistence create - table = "true" * remove - table = "false" * * @ ejb . pk class="java . lang . String" * <! - - end - xdoclet - definition - - > * @ generated * */ public abstract class UserBean implements javax.ejb.EntityBean { /***@ejb.create-method */public java.lang.String ejbCreate(String email, String password) throws javax.ejb.CreateException { // EJB 2.0 spec says return null for CMP ejbCreate methods. setEmail(email); setPassword(password); returnnull; } /*** The container invokes this method immediately after it calls ejbCreate. */publicvoid ejbPostCreate(String email, String password) throws javax.ejb.CreateException { } /*** CMP Field email*@return the email*@ejb.persistent-field *@ejb.persistence* column-name="電子郵件"* jdbc-type="VARCHAR"* sql-type="varchar(64)"* read-only="false"*@ejb.pk-field **@ejb.interface-method */publicabstract java.lang.String getEmail(); /***@param java.lang.String the new email value*@ejb.interface-method */publicabstractvoid setEmail(java.lang.String email); /*** CMP Field password*@return the password*@ejb.persistent-field *@ejb.persistence* column-name="密碼"* jdbc-type="VARCHAR"* sql-type="varchar(64)"* read-only="false" **@ejb.interface-method */publicabstract java.lang.String getPassword(); /***@param java.lang.String the new password value*@ejb.interface-method */publicabstractvoid setPassword(java.lang.String password); }?
?
UserManagementBean.java
/* * 創建日期 2005-1-14 * * 作者:javamxj(分享java快樂) */ package javamxj . ejb . cmp ; /** * * <! - - begin - user - doc - - > A generated session bean <! - - end - user - doc - - > * <! - - lomboz . beginDefinition - - > <?xml version=" 1.0 " encoding="UTF - 8 "?> <lomboz : EJB xmlns : j2ee=" http://java.sun.com/xml/ns/j2ee " xmlns : lomboz=" http://lomboz.objectlearn.com/xml/lomboz "> <lomboz : session> <lomboz : sessionEjb> <j2ee : display - name>UserManagement< / j2ee : display - name> <j2ee : ejb - name>UserManagement< / j2ee : ejb - name> <j2ee : ejb - class>javamxj . ejb . cmp . UserManagementBean< / j2ee : ejb - class> <j2ee : session - type>Stateless< / j2ee : session - type> <j2ee : transaction - type>Container< / j2ee : transaction - type> < / lomboz : sessionEjb> < / lomboz : session> < / lomboz : EJB> <! - - lomboz . endDefinition - - > * * <! - - begin - xdoclet - definition - - > * @ ejb . bean name="UserManagement" * jndi - name="UserManagement" * type="Stateless" * transaction - type="Container" * view - type = "remote" * * @ ejb . ejb - ref * ejb - name = "User" * view - type = "local" * ref - name = "ejb / UserLocal" * * @ jboss . ejb - local - ref * ref - name = "UserLocal" * jndi - name = "UserLocal" * * <! - - end - xdoclet - definition - - > * @ generated */ public abstract class UserManagementBean implements javax.ejb.SessionBean { private UserLocalHome userHome = null; /*** Create method*@ejb.create-method view-type = "remote" */publicvoid ejbCreate() throws javax.ejb.CreateException, javax.naming.NamingException { userHome = UserUtil.getLocalHome(); } publicvoid ejbPassivate() { userHome = null; } /*** Business method*@ejb.interface-method view-type = "remote" */publicvoid addUser(String email, String password) throws javax.ejb.CreateException { UserLocal user = userHome.create(email, password); } /*** Business method*@ejb.interface-method view-type = "remote" */publicvoid removeUser(String email) throws javax.ejb.RemoveException { userHome.remove(email); } /*** Business method*@ejb.interface-method view-type = "remote" */publicboolean verifyPassword(String email, String password) throws javax.ejb.FinderException { UserLocal user = userHome.findByPrimaryKey(email); return user.getPassword().equals(password); } }?
?
CMPClient1.java
/* * 創建日期 2005-1-14 * * 作者:javamxj(分享java快樂) */ package javamxj . ejb . client ; import java . rmi . RemoteException ; import java . util . Hashtable ; import javax . ejb . CreateException ; import javax . ejb . FinderException ; import javax . ejb . RemoveException ; import javax . naming . InitialContext ; import javax . naming . NamingException ; public class CMPClient1 { private javamxj.ejb.cmp.UserManagementHome getHome() throws NamingException { return (javamxj.ejb.cmp.UserManagementHome) getContext().lookup( javamxj.ejb.cmp.UserManagementHome.JNDI_NAME); } private InitialContext getContext() throws NamingException { Hashtable props = newHashtable(); props.put(InitialContext.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); props.put(InitialContext.PROVIDER_URL, "jnp://127.0.0.1:1099"); // This establishes the security for authorization/authentication// props.put(InitialContext.SECURITY_PRINCIPAL,"username");// props.put(InitialContext.SECURITY_CREDENTIALS,"password"); InitialContext initialContext = new InitialContext(props); return initialContext; } publicvoid testBean() { try { javamxj.ejb.cmp.UserManagement myBean = getHome().create(); // 增加4個用戶 myBean.addUser("rick@rickhightower.com", "mypassword"); myBean.addUser("nick@rickhightower.com", "oxford"); myBean.addUser("javamxj@yahoo.com.cn", "分享Java快樂"); myBean.addUser("aaa@bbb.com","ccc"); // 驗證用戶和密碼是否相符boolean login = false; login = myBean.verifyPassword("javamxj@yahoo.com.cn", "分享Java快樂"); System.out.println("Login =" + login); // 刪除用戶 myBean.removeUser("aaa@bbb.com"); //--------------------------------------//This is the place you make your calls.//System.out.println(myBean.callYourMethod()); } catch (RemoteException e) { e.printStackTrace(); } catch (CreateException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } catch (FinderException e) { e.printStackTrace(); } catch (RemoveException e) { e.printStackTrace(); } } publicstaticvoid main(String[] args) { CMPClient1 test = new CMPClient1(); test.testBean(); } }
?
?
后記:
?
??? 這些代碼需要保存好,后面會在此基礎上進一步擴展,開發含有更復雜聯系的程序。
?
??? 下篇文章講述如何設計一對一的雙向聯系。
?
?