2.7 使用MyEclipse可視化開發Hibernate實例
2.7節的例子源代碼在配套光盤sourcecode/workspace目錄的chapter02_first項目中。
這個實例主要演示如何使用MyEclipse的可視化開發工具開發Hibernate應用,利用MyEclipse可以提高我們開發Java EE應用的效率。操作的數據庫表還是guestbook表,所使用MyEclipse的版本為7.0,不同的MyEclipse版本之間對于開發Hibernate應用差異不大。
在7.0版本中,內置了對Hibernate 2.x、3.0、3.1和3.2等Hibernate版本的支持,沒有提供對3.3版本的支持。我們可以修改MyEclipse的設置,把對Hibernate 3.2的支持,修改為對Hibernate 3.3的支持。為此啟動Eclipse后,選中菜單欄的"Windows"→"Preference"→"MyEclipse Enterprise Workbench"→"Project Capabilities"→"Hibernate"→"Hibernate 3.2"選項,在Library Modules下拉列表框中選中Hibernate 3.2 Core Libray選項,把類庫文件替換為Hibernate 3.3的類庫文件。如圖2 2所示。
![]() |
圖2 2 修改MyEclipse中Hibernate 3.2的類庫文件 |
2.7.1 設置MyEclipse連接Oracle數據庫
為在MyEclipse中設置連接Oracle數據庫,在Eclipse中選擇Window→Show View→Other→MyEclipse Database→DB Browser選項。右擊DB Browser視圖的空白部分,選擇New選項,如圖2 3所示。
![]() |
圖2 3 選擇New選項 |
在彈出的窗口中,輸入連接Oracle數據庫所需要的相應參數,以及Oracle驅動類庫的文件名與位置。單擊Next按鈕,如圖2 4所示。
![]() |
圖2 4 輸入連接Oracle數據庫的參數 |
在Schema Details窗口中,選中Display Selected單選按鈕。單擊"Add"按鈕,在彈出的Selection Needed窗口中選中SCOTT復選框。單擊"OK"按鈕,如圖2 5所示。單擊"Finish"按鈕,關閉Schema Details窗口。
![]() |
圖2 5 選擇SCOTT復選框 |
2.7.2 新建項目并增加Hibernate開發支持
在Eclipse中新建一個Java項目,名為"chapter02_first"。單擊MyEclipse→Project Capabilities→Add Hibernate Capabilites選項,增加Hibernate的開發支持,如圖2 6所示。
![]() |
圖2 6 增加Hibernate的開發支持 |
彈出Hibernate Support for MyEclipse窗口,在Hibernate Specification選項組中選中Hibernate 3.2單選按鈕,選擇MyEclipse Libraries和Hibernate 3.2 Core Libaries-<MyEclipse-Library>復選框選項,如圖2 7所示,單擊Next按鈕。
![]() |
圖2 7 選擇Hibernate類庫的版本 |
其中的選項說明如表2-3所示。
表2-3 選項說明
選項 |
描述 |
Hibernate Specification |
要添加到項目中的Hibernate具體版本,推薦選擇Hibernate 3.2 |
Enable Hibernate Annotations Support |
是否需要Hibernate Annotations的支持 |
MyEclipse Libraries/User Libraries |
選擇顯示哪個位置的類庫 |
Add checked Libraries to project build-path |
選中的類庫將會添加當前項目的構建路徑中,但是相應的Jar文件將不會復制到項目中,這些Jar文件會在項目部署時復制 |
Copy checked Library Jars to project folder and add to build-path |
選中的類庫中的Jar文件將會被復制到項目并添加到構建路徑中 |
Library Folder |
一個相對于當前項目的路徑,類庫中的Jar會被復制到其中 |
在接下來的窗口中輸入MyEclipse產生的Hibernate配置文件名及其路徑。使用hibernate.cfg.xml文件名,路徑保留默認值,如圖2 8所示。
![]() |
圖2 8 設置生成hibernate.cfg.xml文件的名稱及其路徑 |
單擊Next按鈕,在DB Driver下拉列表框中選中已設置的oracledriver選項,其他選項保留默認值,如圖2 9所示。
![]() |
圖2 9 選擇要使用的數據庫 |
單擊"Next"按鈕,清除"Create SessionFactory Class"復選框,如圖2 10所示,單擊Finish按鈕結束設置。
![]() |
圖2 10 清除Create SessionFactory Class復選框 |
執行上述操作后,MyEclipse會在項目的構建路徑中增加Hibernate的相關類庫和Oracle的驅動類庫。同時生成了開發Hibernate應用所需的hibernate.cfg.xml文件,整個項目的所有類庫文件和配置文件如圖2 11所示。
![]() |
圖2 11 整個項目的所有類庫文件和配置文件 |
還需要修改MyEclipse自動生成的hibernate.cfg.xml文件,增加一些新的配置項并修改Oracle數據庫方言類的名稱。修改后的hibernate.cfg.xml的內容如下所示(加粗顯示部分為需要修改處)。
- SRC 2 2 hibernate.cfg.xml
- <?xml version='1.0' encoding='UTF-8'?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name=
- "dialect">org.hibernate.dialect.Oracle9iDialect</property>
- <property name=
- "connection.url">jdbc:oracle:thin:@localhost:1521:ora9</property>
- <property name="connection.username">scott</property>
- <property name="connection.password">tiger</property>
- <property name=
- "connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
- <property name="myeclipse.connection.pro
file" >oracledriver</property>- <property name="current_session_context_class">thread</property>
- <property name="show_sql">true</property>
- <property name="format_sql">true</property>
- </session-factory>
- </hibernate-configuration>
2.7.3 自動生成Guestbook類與映射文件
在Eclipse的DB Browser視圖中,右擊設置的oracledriver名。選擇Open connection選項,如圖2 12所示彈出Open Database Connection窗口,輸入用戶名及密碼,如圖2 13所示,單擊OK按鈕。
![]() |
圖2 12 選澤Open Database Connection選項 |
![]() |
圖2 13 輸入用戶名與密碼 |
右擊DB Browser視圖中的guestbook表,選中"Hibernate Reverse Engineering"選項。如圖2 14所示。
![]() |
圖2 14 選擇Hibernate Reverse Engineering選項 |
彈出"Hibernate Mapping and Application Generation"窗口,輸入與生成持久化類(POJO)有關的參數值。在Java src folder文本框中輸入生成持久化類的保存路徑,在Java package文本框中輸入持久化類所使用的包名。選擇"Create POJO<>DB Table mapping information、Create a Hibernate mapping file (*.hbm.xml) for each database table"及"Java Da
![]() |
圖2 15 設置生成POJO類與映射文件 |
單擊Next按鈕,在打開窗口中的Id Generator下拉列表框中選中sequence選項,其他選項保留默認值,如圖2 16所示。
![]() |
圖2 16 選擇主鍵生成策略 |
單擊"Next"按鈕,在打開如圖2 17所示的窗口中單擊"Finish"按鈕。
![]() |
圖2 17 設置逆向工程的細節 |
經過上面的操作之后,MyEclipse會自動生成Guestbook.java和Guestbook.hbm.xml兩個文件。Guestbook.hbm.xml文件的內容如下所示,需要修改008行~第010行的內容用來設置序列名。
- SRC 2 3 Guestbook.hbm.xml
- 001 <?xml version="1.0" encoding="utf-8"?>
- 002 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate
- Mapping DTD 3.0//EN"
- 003 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- 004 <hibernate-mapping>
- 005 <class name="com.v512.examples.Guestbook" table="GUESTBOOK"
- schema="SCOTT">
- 006 <id name="id" type="java.lang.Integer">
- 007 <column name="ID" precision="8" scale="0" />
- 008 <generator class="sequence">
- 009 <param name="sequence">gb_seq</param>
- 010 </generator>
- 011</id>
- 012<property name="name" type="java.lang.String">
- 013 <column name="NAME" length="20" not-null="true" />
- 014</property>
- 015<property name="phone" type="java.lang.String">
- 016 <column name="PHONE" length="20" />
- 017</property>
- 018<property name="email" type="java.lang.String">
- 019 <column name="EMAIL" length="40" />
- 020</property>
- 021<property name="title" type="java.lang.String">
- 022 <column name="TITLE" length="80" not-null="true" />
- 023</property>
- 024<property name="content" type="java.lang.String">
- 025 <column name="CONTENT" length="2000" />
- 026</property>
- 027<property name="createdTime" type="java.util.Date">
- 028 <column name="CREATED_TIME" not-null="true" />
- 029</property>
- 030 </class>
- 031 </hibernate-mapping>
第005行中<class>標簽的schema屬性設置當前表屬于哪個schema,第007行和第013行中<column>標簽的precision、scale及length屬性設置表中字段的精度、小數點位數和長度,not-null屬性設置該字段是否不允許為空。
2.7.4 編寫HibernateSessionFactoryUtil.java文件
在Hibernate應用中,如果只使用一個數據庫,則通常只需要一個SessionFactory對象。為了方便整個應用取得同一個SessionFactory對象,我們應用設計模式中的單態模式。編寫一個SessionFactory的工具類HibernateSessionFactoryUtil,HibernateSessionFactoryUtil.java文件的內容如下:
- SRC 2 4 HibernateSessionFactoryUtil.java
- 001 package com.v512.util;
- 002
- 003 imp
ort org.hibernate.SessionFactory;- 004 imp
ort org.hibernate.cfg.Configuration;- 005
- 006 public class HibernateSessionFactoryUtil {
- 007 private static final SessionFactory sessionFactory;
- 008 static {
- 009 try {
- 010 sessionFactory = new Configuration().configure().
buildSessionFactory();- 011 } catch (Throwable ex) {
- 012 /*
- 013 * 需要 捕獲Throwable對象,
- 014 * 否則捕獲不到 Error及其子類,以及NoClassDefFoundError類型的錯誤
- 015 */
- 016 throw new ExceptionInInitializerError(ex);
- 017 }
- 018 }
- 019
- 020 private HibernateSessionFactoryUtil() {
- 021
- 022 }
- 023
- 024 public static SessionFactory getSessionFactory() {
- 025 return sessionFactory;
- 026 }
- 027 }
HibernateSessionFactoryUtil類在載入JVM后新建Configuration對象,讀取hibernate.cfg.xml文件,創建SessionFactory對象,通過HibernateSessionFactoryUtil類所提供的getSessionFactory()靜態方法獲取SessionFactory對象。
2.7.5 編寫HibernateTest.java
編寫一個測試的HibernateTest.java文件,通過Hibernate實現對guestbook表中數據的CRUD操作,在其中定義addGuestbook()、updateGuestbook()、getGuestbook()、getGuestbooks()、deleteGuestbook()和printGuestbook()方法。該文件的內容如下:
- SRC 2 5 HibernateTest.javaa
- 001 package com.v512.examples;
- 002
- 003 imp
ort java.util.List;- 004 imp
ort org.hibernate.Query;- 005 imp
ort org.hibernate.Session;- 006 imp
ort org.hibernate.Transaction;- 007 imp
ort com.v512.util.HibernateSessionFactoryUtil;- 008
- 009 public class HibernateTest {
- 010 public void addGuestbook(Guestbook gb) {
- 011Session session = HibernateSessionFactoryUtil.
- getSessionFactory().
- getCurrentSession();
- 012 Transaction tx = session.beginTransaction();
- 013 session.save(gb);
- 014 tx.commit();
- 015 }
- 016
- 017 public Guestbook getGuestbook(Integer id) {
- 018 Session session = HibernateSessionFactoryUtil.
- getSessionFactory().
- getCurrentSession();
- 019 Transaction tx = session.beginTransaction();
- 020 Guestbook gb = (Guestbook) session.get
- (Guestbook.class, id);
- 021 tx.commit();
- 022 return gb;
- 023 }
- 024
- 025 public List<Guestbook> getGuestbooks() {
- 026 Session session = HibernateSessionFactoryUtil.
- getSessionFactory().
- getCurrentSession();
- 027 Transaction tx = session.beginTransaction();
- 028 Query query = session.createQuery("from Guestbook");
- 029 List<Guestbook> list = query.list();
- 030 tx.commit();
- 031 return list;
- 032 }
- 033
- 034 public void updateGuestbook(Guestbook gb) {
- 035 Session session = HibernateSessionFactoryUtil.
- getSessionFactory().
- getCurrentSession();
- 036 Transaction tx = session.beginTransaction();
- 037 session.saveOrUpdate(gb);
- 038 tx.commit();
- 039 }
- 040
- 041 public void deleteGuestbook(Integer id) {
- 042 Guestbook gb = getGuestbook(id);
- 043 Session session = HibernateSessionFactoryUtil.
- getSessionFactory().
- getCurrentSession();
- 044 Transaction tx = session.beginTransaction();
- 045 session.delete(gb);
- 046 tx.commit();
- 047 }
- 048
- 049 public void printGuestbook(Guestbook gb) {
- 050 System.out.print("id:" + gb.getId() + "\t");
- 051 System.out.print("name:" + gb.getName() + "\t");
- 052 System.out.print("title:" + gb.getTitle() + "\t");
- 053 System.out.print("content:" + gb.getContent() + "\t");
- 054 System.out.println("createdTime:" + gb.getCreatedTime());
- 055 }
- 056
- 057 public static void main(String[] args) {
- 058 HibernateTest test = new HibernateTest();
- 059 Guestbook gb = test.getGuestbook(new Integer(1));
- 060
- 061 System.out.println("-------------------------
- 讀取單一記錄-----------------------------");
- 062 test.printGuestbook(gb);
- 063
- 064 System.out.println("-------------------------
- 讀取所有記錄-----------------------------");
- 065 List<Guestbook> list = test.getGuestbooks();
- 066 for (Guestbook g : list) {
- 067 test.printGuestbook(g);
- 068 }
- 069
- 070 System.out.println("-------------------------
- 更新記錄---------------------------------");
- 071 gb.setName("關羽");
- 072 test.updateGuestbook(gb);
- 073 test.printGuestbook(gb);
- 074
- 075 System.out.println("-------------------------
- 刪除記錄---------------------------------");
- 076 test.deleteGuestbook(new Integer(1));
- 077
- 078 HibernateSessionFactoryUtil.getSessionFactory().close();
- 079 }
- 080 }
當使用HibernateTest類中getGuestbook()方法根據id值獲取一條記錄時,Hibernate找到數據庫中這條記錄,然后再生成這條記錄所對應的持久化對象返回。updateGuestbook()方法更新一條記錄時首先找到這條記錄所對應的持久化對象,然后調用這個對象的setter方法修改屬性值,并通過Hibernate完成數據庫中數據的更新;deleteGuestbook()方法刪除一條記錄時首先找到這條記錄所對應的持久化對象,然后通過Hibernate刪除持久化對象刪除進而數據庫中所對應的數據。
2.7.6 程序運行結果
這個實例使用Hibernate完成對數據庫中數據的CRUD操作,借助MyEclipse的幫助開發Hibernate應用,不需要手工編寫持久化(POJO)類、Hibernate的配置和映射文件。Hibernate通過操作持久化對象完成對數據庫數據的CRUD操作, HibernateTest.java運行結果如下:
- -------------------------讀取單一記錄-----------------------------
- id:1 name:劉偉 title:大家好
- content:歡迎大家學習Hibernate技術。
- createdTime: 2009-03-12 06:17:59.0
- -------------------------讀取所有記錄-----------------------------
- id:1 name:劉偉 title:大家好
- content:歡迎大家學習Hibernate技術。
- createdTime: 2009-03-12 06:17:59.0
- -------------------------更新記錄---------------------------------
- id:1 name:關羽 title:大家好
- content:歡迎大家學習Hibernate技術。
- createdTime: 2009-03-12 06:17:59.0
- -------------------------刪除記錄---------------------------------
2.7.7 使用 HQL 編輯器調試HQL語句
MyEclipse中包含一個Hibernate編輯器和多個相關視圖,允許根據當前項目的配置來調試HQL語句。"Hibernate Dynamic Query Translator"視圖顯示當前HQL語句所對應的SQL語句;"Hibernate Query Result"視圖查看HQL語句的執行結果,返回的持久化對象的屬性值通過"Properties"視圖顯示;"Query Parameters"視圖可以為調試的HQL語句輸入需要的參數值。
右擊Package Explorer視圖中的chapter02_first項目,選中快捷菜單中的"MyEclipse→Open HQL Editor"選項,如圖2 18所示。
![]() |
圖2-18 MyEclipse→Open HQL Editor選項 |
打開HQL編輯器,輸入"from Guestbook"。單擊運行圖標執行查詢,并且通過相關視圖查看查詢結果,如圖2 19所示。
![]() |
圖2 19 在HQL編輯器中執行HQL查詢并查看結果 |
還可以使用"Query Parameters視圖輸入需要綁定參數的HQL查詢語句,如圖2 20所示。
![]() |
圖2 20 使用Query Parameters 視圖輸入需要綁定參數的HQL查詢語句 |
2.8 Hibernate應用的開發方式
2.8.1 自底向上,從數據庫表到持久化類
采用自底向上的開發方式,采用手工或者MyEclipse等開發工具直接根據數據庫中表的結構生成對應的映射文件和持久化類。這是實際開發中最常用的一種方式,也是本書所推薦的方式。通過這種方式最小化了手工編碼,降低了出錯的可能性。
2.8.2 自上向下,持久化類到數據庫表
首先編寫持久化類,然后根據持久化類的代碼手工編寫或者采用工具生成映射文件,進而生成數據庫表結構。這種方式在實際開發中也經常使用,可能出現的問題是生成的數據庫表結構與實際需要的數據庫表結構之間的差異,需要手工調整。
2.8.3 從中間出發,向上與向下發展
首先編寫持久化類與數據庫表的映射文件,然后根據映射文件手工編碼或者采用工具向上生成持久化類,向下生成數據庫表結構。
2.9 設置Hibernate使用連接池
Hibernate默認使用一個功能簡單的連接池,通常只用于開發階段測試之用。為了更高效地使用Hibernate,可以設置Hibernate使用第三方C3P0或者應用服務器(容器)所帶的數據庫連接池。
2.9.1 設置使用Tomcat中的連接池
如果開發運行在應用服務器中的程序,建議其中配置的連接池,如允許Hibernate使用通過在Tomcat中所配置的連接池。為此修改Tomcat中的context.xml文件,該文件位于tomcat安裝目錄的conf子目錄中,同時還需要將Oracle數據庫的驅動類庫ojdbc6.jar或者ojdbc14.jar添加到tomcat的lib目錄下。修改后的context.xml文件內容如下:
- SRC 2 6 context.xml
- <Context reloadable="true">
- <WatchedResource>WEB-INF/web.xml</WatchedResource>
- <Resource name="jdbc/oracleds" auth="Container"
- type="javax.sql.DataSource" maxActive="100"
- maxIdle="30" maxWait="10 000" username="scott" password="tiger"
- driverClassName="oracle.jdbc.OracleDriver" url=
"jdbc:oracle:thin:@localhost:1521:ora9" />- </Context>
設置Tomcat提供的連接池之后,要在Hibernate的配置文件(hibernate.cfg.xml)中添加connection.datasource屬性,如下面的代碼所示:
- <property name="connection.datasource">
- java:comp/env/jdbc/oracleds</property>
其中的java:comp/env/jdbc/oracleds是Tomcat中設置的數據源對象的JNDI名稱。
2.9.2 使用C3P0連接池
如果讓Hibernate使用第三方C3P0連接池,則在Hibernate的配置文件中添加如下的配置信息,還需要把C3P0類庫添加到當前項目的構建路徑下。
- <property name="connection.provider_class">
- org.hibernate.connection.C3P0ConnectionProvider
- </property>
- <property name="hibernate.c3p0.min_size">5</property>
- <property name="hibernate.c3p0.max_size">10</property>
- <property name="hibernate.c3p0.max_statements">50</property>
- <property name="hibernate.c3p0.timeout">3600</property>
- <property name="hibernate.c3p0.idle_test_period">120</property>
- <property name="hibernate.c3p0.acquire_increment">2</property>
- hibernate.c3p0.min_size:設置連接池的最小連接數。
- hibernate.c3p0.max_siz:設置連接池的最大連接數。
- hibernate.c3p0.timeout:設置連接池中的連接的最大空閑時間,超時后會被刪除,單位為秒。
- hibernate.c3p0.max_statements:設置連接池中Statement對象的最大數量。
- hibernate.c3p0.idle_test_period:設置檢查連接池中空閑連接的間隔時間,單位為秒。
- hibernate.c3p0.acquire_increment:設置連接池的連接用完后每次新建連接的數量。
2.9.3 使用自定義連接池
在Hibernate應用中還可以使用定義連接池,該連接池需要實現org.hibernate.connection.ConnectionProvider接口,并在Hibernate配置文件中設置hibernate.connection.provider_class屬性,其值為這個實現類的名稱。
2.10 使用C3P0連接池
2.10節的例子源代碼在配套光盤sourcecode/workspace目錄的chapter02_first項目中。
2.10.1 創建chapter02_c3p0項目
在這個實例中讓Hibernate使用第三方C3P0連接池獲取操作數據庫的連接對象,通過復制chapter02_first項目創建chapter02_c3p0項目。同時還需要把C3P0連接池的類庫(c3p0-*.*.*.jar)添加到當前項目的構建目錄下。當前項目構建路徑中的類庫如圖2 21所示。
![]() |
圖2 21 chapter02_c3p0項目構建路徑中的類庫 |
2.10.2 編輯hibernate.cfg.xml文件
當前項目使用了C3P0的連接池技術,修改hibernate.cfg.xml文件以配置相應的參數,其內容如下:
- SRC 2 7 hibernate.cfg.xml
- <?xml version='1.0' encoding='UTF-8'?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net
- /hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="connection.driver_class">oracle.jdbc.driver.
- OracleDriver</property>
- <property name="connection.url">jdbc:oracle:thin:@localhost:
- 1521:ora9</property>
- <property name="dialect">org.hibernate.dialect.
- Oracle9iDialect</property>
- <property name="connection.username">scott</property>
- <property name="connection.password">tiger</property>
- <!-- C3P0 連接池的配置 -->
- <property name="connection.provider_class">
- org.hibernate.connection.C3P0ConnectionProvider
- </property>
- <property name="hibernate.c3p0.min_size">5</property>
- <property name="hibernate.c3p0.max_size">10</property>
- <property name="hibernate.c3p0.max_statements">50</property>
- <property name="hibernate.c3p0.timeout">3600</property>
- <property name="hibernate.c3p0.idle_test_period">120</property>
- <property name="hibernate.c3p0.acquire_increment">2</property>
- <property name="current_session_context_class">thread</property>
- <property name="show_sql">true</property>
- <property name="format_sql">true</property>
- <mapping resource="com/v512/examples/Guestbook.hbm.xml" />
- </session-factory>
- </hibernate-configuration>
2.10.3 chapter02_c3p0項目的運行與輸出
chapter02_c3p0項目中,其他文件都不需要修改,運行HibernateTest類輸出的結果chapter02_first項目運行輸出結果完全一樣。