IBM WebSphere 開發者技術期刊: 開發用于 WebSphere Application Server 的 H

發表于:2007-06-22來源:作者:點擊數: 標簽:
級別: 中級 Sunil Patil (sunilpatil@in.ibm.com) 軟件工程師, IBM 2004 年 11 月 本文一步一步地指導我們在創建 Hibernate 應用程序的時候,使用 Websphere Application Server 的連接以及事務管理。 獲取本文中所使用的產品以及工具 如果您是 developerW

   

級別: 中級

Sunil Patil (sunilpatil@in.ibm.com)
軟件工程師, IBM
2004 年 11 月

本文一步一步地指導我們在創建 Hibernate 應用程序的時候,使用 Websphere® Application Server 的連接以及事務管理。

獲取本文中所使用的產品以及工具
如果您是 developerWorks 的訂戶,就會擁有單用戶的使用許可,以使用 WebSphere Application Server 和其他 DB2®, Lotus®, Rational®, Tivoli® 產品,包括基于 Eclipse 的 WebSphere Studio IDE -- 來開發、測試、評估以及演示您的應用程序。如果您不是 developerWorks 的訂戶,現在可以預定。

前言
Hibernate 是一個流行的開源對象關系映射工具,運行在 Java 環境中。用基于 SQL 的模式可以把數據呈現從對象模型映射到關系數據模型,對象關系映射引用了這項技術。這也就意味著在與數據庫交互時,Hibernate 提供了多級抽象方法。

Hibernate 非常靈活,并且支持多種使用方法。在一種情況下,使用 Hibernate API 的最小子集,它僅僅可以用來同數據庫交互,在這種情況下,應用程序必須為自己提供連接并且管理自己的事務;例如 WebSphere Application Server 這樣的中間件可以實現這些功能。在另一種情況下,即使您沒有運行中間件,您也可以使用完整版本的 Hibernate,在這種情況下,您向 Hibernate 提供數據庫配置信息,這時它不僅僅為您創建和管理連接,而且還可以通過把事務委派到底層數據庫來管理它們。

使用 Hibernate,您需要創建 Java 類來描述數據庫中的表,并且將類中的實例變量映射到數據庫中的列。這時,正如您所想的那樣,您可以調用 Hibernate 的方法來選擇、插入、更新和刪除底層表中的記錄,而不是自己創建和執行查詢。

Hibernate 架構有三個主要的組件:

  • 連接管理
    因為在于數據庫交互時,打開以及關閉數據庫的開銷是非常昂貴的,您應該將您的數據庫連接放在池中并且能重新使用。
  • 事務管理
    在一個批處理中執行多個查詢時,會用到事務;結果可能是所有的查詢都成功,或者是所有的都失敗。
  • 對象關系映射
    在這部分中,特定的 Java 對象 Hibernate 來插入或者更新數據;例如,當您傳遞一個對象的實例到 Session.save() 方法時,Hibernate 將讀取這個對象實例變量的狀態,并且創建和執行必須的查詢。在選擇查詢的情況下,將返回描述結果集的對象。

Hibernate 非常的靈活,并且提供多種途徑來使用這些組件:

  • “Lite”架構
    當您僅僅想要使用 Hibernate 對象關系映射組件時使用。在這種情況下,您需要自己實現連接以及事務管理,例如,用 WebSphere Application Server。
  • “Full cream”架構
    當您想要應用所有三個 Hibernate 組件時使用。Hibernate 可以為您管理連接,但是您必須通過 XML 配置提供如驅動程序類名、用戶名、密碼以及其他一些連接信息。當管理事務的時候,您可以在 Hibernate 對象上調用開始、提交以及回滾方法。

當涉及到對象關系映射時,Hibernate 是非常好的工具,但是在連接管理以及事務管理方面,它卻缺乏必要的性能和能力。幸運的是,我們可以將 Hibernate 的對象關系映射與 WebSphere Application Server 的連接和事務管理結合起來,創建強大的應用程序。

本文假設您已經具備了 Hibernate、Enterprise JavaBean(EJB)組件以及 Struts 的基礎知識。如果您剛剛接觸 Hibernate,請參考沒有對象的對象關系映射,這篇文章討論了怎么用 Hibernate 來實現簡單的插入、更新以及刪除操作。

關于示例應用程序
為了實現本文的目的,我們將創建一個簡單的 Struts Web 應用程序,它允許用戶來向 Contact 表中插入新的記錄。我們的示例應用程序將使用 AddContact.jsp 來接收用戶的輸入。AddContactAction.java 是活動類,它將用 Hibernate 來插入一個新的聯系人到數據庫中去。如果聯系人成功插入,這時用戶被重定向到 suclearcase/" target="_blank" >ccess.jsp,這個頁面將顯示最新插入聯系人的詳細信息。如果遇到了問題,將顯示 failure.jsp 頁面。

圖 1. 實例應用程序插入頁面
圖 1. 實例應用程序插入頁面

使用 Hibernate
開始時,我們將創建實例應用程序,這個程序使用 Hibernate 自己的連接池以及事務管理(同樣請參考 "full cream" 架構):

  1. 創建一個 Struts 應用程序,既可以使用 WebSphere Studio Application Developer(以后稱作 Application Developer),也可以通過導入包含在 Struts 發布里面的 struts-blank.war 來實現。為示例應用程序創建必須的 JSP 頁面和活動類,您也可以從下載文件 sample1.zip中導入。
  2. 從 Hibernate 網站上下載 Hibernate 二進制版本:復制 hibernate2.jar 以及 JAR 庫文件(dom4j.jar,xmlapi.jar及其他),到 WEB-INF/lib 目錄中。
  3. 創建 Contact.java 類,并且為 Contact 中的每一列創建一個成員變量。每個字段都應該創建 Getter 和 Setter 方法。同樣需要創建 contact.hbm.xml 文件,這個文件將把 Contact.java 的實例變量映射到 Contact 表的列上。
  4. 在您的源代碼根目錄中創建 hibernate.cfg.xml。這個文件為 Hibernate 保存應用程序級別的配置信息,正如清單 1 所示的那樣。

    清單 1

    
    <hibernate-configuration>
    <session-factory>
    <property name="hibernate.connection.driver_class">
    COM.ibm.db2.jdbc.app.DB2Driver</property>
    <property name="hibernate.connection.url">jdbc:db2:SAMPLE</property>
    <property name="hibernate.connection.username">db2admin</property>
    <property name="hibernate.connection.password">db2admin</property>
    <property name="hibernate.connection.pool_size">10</property>
    <property name="show_sql">true</property>
    <property name="dialect">net.sf.hibernate.dialect.DB2Dialect</property>
    <property name="hibernate.hbm2ddl.auto">create-drop</property>
    <!-- Mapping files -->
    <mapping resource="contact.hbm.xml"/>
    </session-factory>
    </hibernate-configuration>
    

    在這個文件中:
    • 您將注意到如果需要用純 JDBC 打開連接,我們必須在這里指定同樣的信息:
      • hibernate.connection.driver_class 是我們決定要使用的 JDBC 驅動器類。
      • hibernate.connection.passwordhibernate.connection.username 是數據庫的信任狀。
      • hibernate.connection.url 是用來連接數據庫的 JDBC URL。
    • dialect 屬性決定了在獲取查詢的時候用到的專用語。Hibernate 支持所有流行的關系數據庫管理系統(RDBMS)的專用語,例如 DB2 或者 Oracle™。因此,例如,如果您在開發過程中使用 Oracle,并且在生產的時候想要轉移到 DB2 上,僅僅需要改變 hibernate.cfg.xml 文件。
    • hibernate.hbm2ddl.auto 可以用來指示 Hibernate,當我們初始化它時,從映射文件為我們的應用程序創建 DDL,并且在數據庫中創建這些表和序列。create-drop 的值意味著當 Hibernate 關閉時將刪除由 Hibernate 創建的表。
    • contact.hbm.xml 是 Contact 標的映射文件。如果您有多個表,您即可以創建多個映射文件(每個表一個),以及添加多個 <mapping> 元素,也可以在一個文件中創建多個映射,并且添加一個 <mapping> 元素。
    在我們的應用程序接下來的部分,我們將讀取由用戶輸入的值,并且向 Contact 表中插入一條新的記錄。AddContactAction.java 類執行這個方法:

    清單 2

    
    SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
    Session session = sessionFactory.openSession();
    
    //Create new instance of Contact and set values in it by reading them from form object
    Contact contact = new Contact();
    contact.setFirstName((String)contactForm.get("firstName"));
    session.save(contact);
    
    // Actual contact insertion will happen at this step
    session.flush();
    session.close();
    

  5. 通過指定 new Configuration().configure().buildSessionFactory() 來初始化 Hibernate。Hibernate 會設法在根目錄中定位 /hibernate.cfg.xml,如果發現的話就會加載它,并且提供給我們一個到 SessionFactory 的引用,我們可以用它來同 Hibernate 交互。會話(session)指示了一個邏輯上的交互;在一個會話中您可以激活多個查詢。
  6. 為了插入聯系人,創建一個 Contact 類的新實例。通過調用 setter 方法來用輸入的聯系人信息設定各個字段的值,這時把這個聯系人對象傳遞給 Hibernate,調用 session.save() 來保存。Hibernate 將負責生成和執行插入查詢。當聯系人被插入時,Contact 類中 ID 字段的值將和 Contact 表中最新插入的記錄主鍵值相同。如果出現任何問題,Hibernate 將會拋出異常。

請您確認復制 JDBC 驅動器 JAR 文件到 WEB-INF/lib 目錄中,否則將出現異常。

為了嘗試這個示例,請下載 sample1.zip 文件。

通過 WebSphere Application Server 連接池來使用 Hibernate
基于上面我們已經完成的內容,我們可以改進示例聯系人管理應用程序,它包含 WebSphere Application Server 一些關鍵特性的使用。

首先,在開發上面的應用程序時,我們用了 Hibernate 中的連接池。這個連接池算法有點不成熟,并且并不能用在生產環境里面,您應該考慮使用第三方的連接池比如 Apache's DBCP。我們將更改我們的應用程序,來使用 WebSphere Application Server 的連接池:

  1. 為了使用 WebSphere Application Server 連接池,需要創建一個 JDBC 數據源并設定 JNDI 名,比如 jdbc/ds1。(參考 WebSphere Application Servers Information Center 來查看配置數據源的細節。)在 hibernate.cfg.xml 文件中,移除 hibernate.connection.driver_class、URL 以及其他屬性,并且添加這一行:

    <property name="hibernate.connection.datasource">jdbc/ds1</property>

  2. AddContactAction.java 執行方法中,我們每次都創建一個 SessionFactory 對象,但這并不是一個好主意,因為使用 SessionFactory 創建由所有應用程序線程共享的線程安全對象是非常昂貴的。我們應該僅僅在應用程序啟動的時候創建 SessionFactory 對象。我們可以創建一個 SessionContextListener 類并且通過配置 SessionFactory 來實現它,也可以通過更好的辦法,創建一個配置 SessionFactory 的 Struts 插件來實現,如清單 3 所示。

    清單 3

    
    public class HibernateStrutsPlugIn implements PlugIn{
    
    	public void init(ActionServlet arg0, ModuleConfig arg1)
    	throws ServletException {
    		try {
    			SessionFactory sessionFactory = new 
    			Configuration().configure().buildSessionFactory();
    		} catch (HibernateException e) {
    				System.out.println("Error in 
    			configuring SessionFactory");
    				e.printStackTrace();
    
    		}
    	}
    
    	// Other methods
    }
    

    為了創建 Structs 插件:
    1. 創建實現 PlugIn 接口的 HibernateStrutsPlugin 類。在這個類的 init() 方法中,調用 Configuration().configure().buildSessionFactory() 方法。
    2. struts-config.xml 中為新的插件類添加條目,既可以通過使用 Application Developer(圖 2)來實現,也可以通過手動編輯 struts-config.xml 并且在末端添加清單 4 中的那一行。

      圖 2. Struts Configuration File Editor
      圖 2. Struts Configuration File Editor

      清單 4

      
      <struts-config>
      <plug-in className="com.sample.util.HibernateStrutsPlugIn">
      </plug-in>
      </struts-config>
      

    3. 我們將對 hibernate.cfg.xml 文件做一些修改,使重新使用 SessionFactory 更加得容易。通過添加下面的條目,我們告訴 Hibernate 當我們調用 Configuration().configure() 時,它應該創建 SessionFactory 的一個實例,并且將它同 HibernateSessionFactory 綁定在一起。當把 SessionFactory 綁定到 JNDI 時,Hibernate 將在初始化 InitialContext 時使用 hibernate.jndi.url 以及 hibernate.jndi.class 的值。如果這些值沒有指定,將使用默認的 InitialContext 值。

      <property name="hibernate.session_factory_name"> HibernateSessionFactory</property>

  3. 我們將更新我們的應用程序并且添加兩個新表:Phone 和 Address。同樣我們必須更改 AddContact.jsp 來添加這兩個新的輸入。我們想要應用程序完成的功能是,如果用戶指定了電話號碼或者是地址,一條新的記錄將添加到合適的表中。另外,所有這些都應該是一個事務的一部分,也就是說,在添加聯系人和電話號碼以后,在添加地址是突然出現了錯誤,這時所有與該事務關聯活動都應該回滾,并且將向用戶顯示出錯頁面。

    創建 Address.javaPhone.java 來描述 Address 以及 Phone 表,并且通過 address.hbm.xmlcontact.hbm.xml 來映射。在 hibernate.cfg.xml 中為這兩個文件添加 <mapping> 元素。

    清單 5

    
    try {
    	Context ctx = new InitialContext();
    	Object obj = ctx.lookup("HibernateSessionFactory");
    	sessionFactory = (SessionFactory) obj;
    } catch (NamingException e) {
    		e.printStackTrace();
    }
    session = sessionFactory.openSession();
    Transaction contactInsertTransaction = 
    try{
    	session.beginTransaction();
    	//Create new instance of Contact and set values in it by reading them from form object
    	Contact contact = new Contact();
    	// Prepare contact object
    	session.save(contact);
    
    	//Check if value for phone is not null if yes then insert it in db
    	String phoneStr = (String) contactForm.get("phone");
    	if (phoneStr.length() != 0) {
    		//Code for inserting new phone here
    }
    	
    	//If you uncomment this line you will find out contact gets inserted 
    	//even if there is some problem afterwards\
    	/*	if(true)
    		throw new RuntimeException("Test transaction exception"); */
    	// Code for inserting new Address
    	contactInsertTransaction.commit();
    } catch (HibernateException e) {
    	contactInsertTransaction.rollback();
    	return mapping.findForward("failure");
    }finally{
    	session.flush();
    session.close();
    }
    

由于這些改變,我們已經:

  • 改變了執行方法,從 JNDI 中獲得 SessionFactory 引用。
  • 改變了執行方法,使聯系人、電話和地址的插入操作運行在 Hibernate 自己管理的事務中。

如果所有的東西都運行正常,我們將在關閉會話以前提交事務。如果出現了任何問題,我們將調用事務對象中的 rollback() 方法。

利用 WebSphere Application Server 事務管理來使用 Hibernate
第二,現在我們想要更改我們的應用程序,使非 Web 客戶端也可以訪問。為了實現這個目標,我們將創建一個無狀態會話 Bean,并且對外公開一個 addContact() 方法,并且,把所有的業務邏輯從 AddContactAction 類中移動到 ContactBean.java 中。

因為移動到無狀態會話 Bean 的緣故,我們必須初始化 Hibernate 的方法。對于綁定對象來說,JNDI 一旦可用,就應該初始化 Hibernate,并且應該把 SessionFactory 對象綁定到 JNDI。當應用程序服務器已經完成了啟動以后,WebSphere Application Server 就會允許我們注冊回滾通知。

  1. 在 Application Developer 中創建一個名為 sampleListener 的 Java 項目,并且在這個項目中,創建 HibernateJNDIListener.java,如清單 6 所示。

    清單 6

    
    public class HibernateJNDIListener implements CustomService, 
    NotificationListener {
    	public void initialize(Properties arg0) throws 
    	Exception {
    		NotificationFilterSupport filter = new 
    	NotificationFilterSupport();
    		filter.enableType(NotificationConstants.TYPE_J2EE
    	_STATE_RUNNING);
    		ObjectName target = new 
    		ObjectName("WebSphere:*,type=Server");
    		AdminServiceFactory.getAdminService().addNotificationListenerExtended(target,this,filter,null);
    	}
    
    	public void handleNotification(Notification arg0, Object arg1) {
    	try {
    		TestConfiguration.init();
    		System.out.println("Hibernate configured sucessfully");
    		} catch (HibernateException e) {
    			e.printStackTrace();
    		}
    	}
    }
    

  2. 使用 WebSphere Application Server 中的管理控制臺,創建并且注冊名為(HibernateJNDIListener)的類,這個類實現了 CustomService 接口。

    圖 3. WebSphere 管理控制臺
    圖 3. WebSphere 管理控制臺

    當應用程序服務器或者節點啟動時,這個類也將啟動,并且 initialize() 方法中獲取控制權,該方法將注冊一個 HibernateJNDIListner 實例用來接收 TYPE_J2EE_STATE_RUNNING 通知。HibernateJNDIListner 類實現了 NotificationListener 來指明它現在已經可以接收通知。當綁定對象可以使用 WebSphere Application Server 中的 JNDI 時,它將調用 HibernateJNDIListener 中的 Notification() 處理方法。在這個方法中,我們將初始化 SessionFactory 并且將其在 JNDI 中綁定。

  3. 如果要使其工作正常,所有的 Hibernate 映射類和 .hbm.xml 文件需要與 sampleListener.jar 在同一個級別上。創建一個新的 Java 項目,sampleDB,并且將 com.sample.db Java 文件移動到這個項目中,.hbm.xmlhibernate.cfg.xml 文件也是一樣處理。
  4. sampleDB.jarsampleListener.jar 復制到 appserver\lib 中,以下文件也一樣處理:
    • hibernate2.jar
    • do dom4j.jar
    • cgilib-full-2.0.1.jar
    • xml-apis.jar
    • commons-collection-2.1.jar
    • ecache-0.7.jar.
  5. 啟動 WebSphere Application Server,并且檢查 systemout.log,找到表明 Hibernate 配置成功的消息。
  6. 現在,我們將使用 WebSphere Application Server 事務管理來更改我們的應用程序,這樣我們添加的聯系人信息將變為現有事務的一部分。例如,在插入新的聯系人信息以后,我們可能想要發送一個確認信給用戶。如果我們已經有了一個消息驅動 Bean 來發送 e-mail,這個附加的信息應該是一個事務中的一部分。我們可以通過在 hibernate.cfg.xml 中添加這個條目,來與 WebSphere Application Server 事務管理結合在一起。

    <property name="net.sf.hibernate.transaction.JTATransactionFactory"> net.sf.hibernate.transaction.WebSphereTransactionManagerLookup</property>

在這個例子中,我們不會手動指定事務的邊界。WebSphere Application Server 在它調用 addContact() 方法時將開始一個新的事務。如果該方法正常完成了執行操作,沒有拋出任何錯誤,這時事務將被提交,否則將回滾。

結束語
當使用 Hibernate 的時候,如果您沒有應用服務器,就應該使用完整的架構;例如,您有一個要與數據庫交互的 SWING 應用程序。在這種情況下 Hibernate 可以節省您很多低級別的消耗。然而,如果您運行了中間件,您可以使用 WebSphere Application Server 中配置的數據源,因為它為性能做了優化,并且您可以在部屬的多個應用程序中共享同樣的連接池。

對于企業應用程序,您可能有數據庫、消息系統以及各種 EIS 系統,并且您想所有需要的系統都可以運行在一個事務中。在這種情況下,您應該在 Hibernate 中使用 WebSphere Application Server 提供的 Java Transaction API(JTA);當 Hibernate 管理事務時,它通過把調用委托給底層數據庫來實現這一點,但是當它是跨系統而不是數據庫時,將會出現問題。

參考資料

  • 您可以參閱本文在 developerWorks 全球站點上的 英文原文。

  • 用 Struts 來構建開源的 MVC 應用

  • 用 WebSphere Studio V5 來編寫簡單的 struts 應用程序

  • Struts 用戶指南

  • Modifying an Application to use DynaActionForm

  • 使用 Hibernate 將您的 Java 對象持久化到 IBM DB2 Universal Database 中

  • 無容器的對象關系映射

  • WebSphere 零售圖書

下載
Name Size Download method
sample1.zip 5.0 MB FTP|HTTP
sample2.zip 5.0 MB FTP|HTTP
sample3.zip 5.6 MB FTP|HTTP
關于作者
Sunil Patil 是一個在 IBM 印度公司 Lotus 部門的一位軟件工程師。他具有四年的 J2EE 經驗。

原文轉自:http://www.anti-gravitydesign.com

国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97