Hibernate入門 ++YONG原創,轉載請聲明 1. 應用程式的分層體系結構: 1.1. 典型的三層結構: 1.1.1. 表示層:提供資料輸入、檢驗與資料呈現的應用程式元件。(GUI、web頁面)。就是與使用者打交道的UI界面。 1.1.2. 業務層:提供商業邏輯服務的應用程式元件。 1.1.3. 資料層:負責存放和管理應用的持久性業務資料的持久化存儲系統。(Database、XML),最常見的持久化存儲系統就是廣泛使用的關系資料庫。 1.2. 軟體層的特征: 1.2.1. 每個層由一組相關的類或元件構成,共同完成特定的功能。 1.2.2. 層與層之間存在自上而下的依賴關系。即上層元件會通路下層元件的API,而下層元件不應該依賴上層元件。如:表現層依賴于業務邏輯層,而業務邏輯層依賴于資料層。 1.2.3. 每個層對上層公開API,封裝實作細節。當某一層的實作發生改變,隻要它的API不變,不會影響其他層的實作。 1.3. 軟體分層的優點: 1.3.1. 伸縮性強:能支援更多的使用者。 1.3.2. 可維護性高:修改軟體的某一層的實作,不會影響其他層。 1.3.3. 可擴充性強:增加新功能更容易,每個層中都有擴充點,不會打破應用的整體架構。 1.3.4. 可重用性高:同一程式能滿足多種需求。 1.3.5. 可管理性高:工作、管理子產品化。 1.4. 四層結構: 由于資料存儲方式多樣,業務層不僅要負責業務邏輯的處理,還要跟資料層互動,提供對業務資料的CRUD操作(create、retrieve、update、delete)。為了把業務資料通路細節和業務邏輯分開,把業務資料通路作為單獨的持久層。是以目前流行的軟體分層結構是: 1. 表示層: 2. 業務層:業務邏輯層負責完成應用程式的邏輯功能,包括 調用持久層完成實體對象的存取、安全檢查,事務控制等。抽象出業務邏輯層的好處是将應用程式的邏輯功能從表示層中剝離,這樣就能複用邏輯層的功能。此外,業務邏輯層也可以看作是對持久層的一個門面模式,簡化表示層對這些邏輯功能的調用。 3. 持久層:封裝了業務資料通路細節,為業務層提供了面向對象的API。 持久層負責實作所有的資料通路功能,它将上層傳入的資料寫入到持久化存儲系統中,并根據上層的要求讀取或修改現有的資料。 4. 資料層: 1.5. 完善的持久層應該達到以下目标: l 代碼可重用性高,能夠完成所有的資料通路操作。 l 具有相對獨立性,當持久層的實作細節發生變化,不會影響上層的實作。 2. ORM簡介: 1. ORM(Object-Relation Mapping)對象-關系映射模式指的是在單個元件中負責所有實體域對象的持久化,封裝資料通路的細節。 2. Hibernate就是一個開源的ORM中間件。(官方網站: http://www.hibernate.org/) 3. Hibernate簡介: 2001年未 Hibernate 第一個版本發表,2003年6月8日 Hibernate 2 發表,并于年未獲得 Jolt 2004 大獎,後被 JBOSS 收納而成為其子項目之一,2005年3月 Hibernate 3 正式發表,當中有了一些重大的改變,本文使用的版本為Hibernate 3.2。 4. 配置 hibernate: 4.1. 準備好所需的jar包: 到官方網站: http://www.hibernate.org/6.html 下載下傳(目前版本:Hibernate Core 3.2.3GA ) hibernate包。解開壓縮包。在lib目錄下找到以下hibernate應用所必須的包(可以檢視該目錄下的_README.txt檔案來确定哪些包是必需的): 1. hibernate.jar :hibernate核心包。必需的。 2. antlr.jar :Hibernate使用ANTLR來産生查詢分析器,這個類庫在運作環境下時也是必需的。 3. cglib.jar :CGLIB庫,Hibernate用它來實作PO位元組碼的動态生成,非常核心的庫,必需的jar包。 4. asm.jar :ASM位元組碼庫,cglib.jar包依賴的包。必需的jar包。 5. asm-attrs.jar :ASM位元組碼庫,cglib.jar包依賴的包。必需的jar包。 6. commons-collections.jar :Apache Commons包中的一個,包含了一些Apache開發的集合類,功能比java.util.*強大。必須使用的jar包。 7. commons-logging.jar :Apache Commons包中的一個,包含了日志功能,必須使用的jar包。這個包本身包含了一個Simple Logger,但是功能很弱。在運作的時候它會先在CLASSPATH找log4j,如果有,就使用log4j,如果沒有,就找JDK1.4帶的java.util.logging,如果也找不到就用Simple Logger。必需的。 8. ehcache.jar :Hibernate可以使用不同cache緩存工具作為二級緩存。EHCache是預設的cache緩存工具。如果沒有其它的可選緩存工具,則為必需的。 9. jta.jar :JTA規範,當Hibernate使用JTA的時候需要。必需的。 10. dom4j.jar :dom4j是一個Java的XML API,類似于jdom,用來讀寫XML檔案的。Hibernate使用dom4j解析XML配置檔案和XML映射元檔案。必需的。 11. log4j.jar :日志包,可選的。 把以上必需的jar放置到應用程式的類路徑中(web應用的WEB-INF/lib目錄下)。 4.2. 基本的Hibernate配置檔案: 在WEB-INF/classes目錄下建立一hibernate.cfg.xml(在官方下載下傳的包etc目錄下有樣闆檔案):
<? 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" > com.mysql.jdbc.Driver </ property > < property name = "connection.url" > jdbc:mysql://localhost:3306/demo </ property > < property name = "connection.username" > root </ property > < property name = "connection.password" > root </ property > <!-- SQL 方言 --> < property name = "dialect" > org.hibernate.dialect.MySQLInnoDBDialect </ property > <!-- 實際操作資料庫時是否顯示 SQL --> < property name = "show_sql" > true </ property > <!-- 将資料庫 schema 的 DDL 導出到資料庫 --> <!-- property name = "hibernate.hbm2ddl.auto" > create </ property!-- > <!-- 以下設定對象與資料庫表的映像檔案 --> ...... </ session-factory > </ hibernate-configuration > |
5. 第一個Hibernate應用程式: 5.1. 建立一個持久化類: 持久化類就是其執行個體要被持久化到資料庫中的類,通常都是實體域類,它是帶有一些屬性及屬性的getters、setters方法的POJO類:
package org.qiujy.demo; public class User { private Integer id ; private String name ; private Integer age ; public User(){} public Integer getAge() { return age ; } public void setAge(Integer age) { this . age = age; } public Integer getId() { return id ; } public void setId(Integer id) { this . id = id; } public String getName() { return name ; } public void setName(String name) { this . name = name; } } |
5.2. 準備好資料庫表: 在MySQL中新增一個demo資料庫,并建立user表:
CREATE TABLE user ( id INT(11) NOT NULL auto_increment PRIMARY KEY, name VARCHAR(100) NOT NULL default '', age INT ); |
5.3. 建立對象-關系映射檔案: Hibernate需要知道怎樣去加載(load)和存儲(store)持久化類的對象。這正是Hibernate映射檔案發揮作用的地方。映射檔案告訴Hibernate應該通路資料庫(database)裡面的哪個表(table)以及應該使用表裡面的哪些字段(column)。 在持久化類所在的包的目錄下建立一名為User.hbm.xml的映射檔案:
<? xml version = "1.0" encoding = "utf-8" ?> <! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" > < hibernate-mapping > < class name = "org.qiujy.demo.User" table = "user" > < id name = "id" column = "id" type = "java.lang.Integer" > < generator class = "native" /> </ id > < property name = "name" column = "name" type = "java.lang.String" /> < property name = "age" column = "age" type = "java.lang.Integer" /> </ class > </ hibernate-mapping > |
5.4. 在Hibernate配置檔案hibernate.cfg.xml中指明映射檔案的位置:
< session-factory > <!-- 以下設定對象與資料庫表的映像檔案 --> < mapping resource = "org/qiujy/demo/User.hbm.xml" /> </ session-factory > |
5.5. 使用Hibernate API進行持久化操作: 1. 建立一輔助類:由這個輔助類來建立一個線程安全的、全局的SessoinFactory,SessionFactory可以建立并打開新的單線程的Session。
package org.qiujy.common; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; public class HibernateSessionFactory { private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml"; private static final ThreadLocal threadLocal = new ThreadLocal(); private static final ThreadLocal txThreadLocal = new ThreadLocal(); private static Configuration configuration = new Configuration(); private static org.hibernate.SessionFactory sessionFactory; private static String configFile = CONFIG_FILE_LOCATION; private HibernateSessionFactory() { } public static Session getSession() throws HibernateException { Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) { if (sessionFactory == null) { rebuildSessionFactory(); } session = (sessionFactory != null) ? sessionFactory.openSession() : null; threadLocal.set(session); } return session; } public static void rebuildSessionFactory() { try { configuration.configure(configFile); sessionFactory = configuration.buildSessionFactory(); } catch (Exception e) { System.err .println("%%%% Error Creating SessionFactory %%%%"); e.printStackTrace(); } } public static void closeSession() throws HibernateException { Session session = (Session) threadLocal.get(); threadLocal.set(null); if (session != null) { session.close(); } } public static org.hibernate.SessionFactory getSessionFactory() { return sessionFactory; } public static void setConfigFile(String configFile) { HibernateSessionFactory.configFile = configFile; sessionFactory = null; } public static Configuration getConfiguration() { return configuration; } public static void beginTransaction(){ Transaction tx = (Transaction)txThreadLocal.get(); if(tx == null){ tx = getSession().beginTransaction(); txThreadLocal.set(tx); } } public static void commitTransaction(){ Transaction tx = (Transaction)txThreadLocal.get(); if(tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){ tx.commit(); txThreadLocal.set(null); } } public static void rollbackTransaction(){ Transaction tx = (Transaction)txThreadLocal.get(); txThreadLocal.set(null); if(tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){ tx.rollback(); } } } |
2. 持久化操作類:
package org.qiujy.dao.impl; import org.apache.log4j.Logger; import org.hibernate.HibernateException; import org.hibernate.Session; import org.qiujy.common.HibernateSessionFactory; import org.qiujy.domain.User; public class UseDaoHBImpl { private static Logger myLogger = Logger.getLogger(UseDaoHBImpl. class ); public void saveUser(User user) { Session session = HibernateSessionFactory.getSession(); try { HibernateSessionFactory.beginTransaction(); session.save(user); HibernateSessionFactory.commitTransaction(); } catch (HibernateException e) { HibernateSessionFactory.rollbackTransaction(); myLogger .error( " 新增使用者失敗 " , e); } finally { HibernateSessionFactory.closeSession(); } } public void removeUserByID( int id){ Session session = HibernateSessionFactory.getSession(); try { HibernateSessionFactory.beginTransaction(); User user = (User) session.get(User. class , new Integer(id)); session.delete(user); HibernateSessionFactory.commitTransaction(); } catch (HibernateException e) { HibernateSessionFactory.rollbackTransaction(); myLogger .error( " 新增使用者失敗 " , e); } finally { HibernateSessionFactory.closeSession(); } } public void updateUser(User user){ Session session = HibernateSessionFactory.getSession(); try { HibernateSessionFactory.beginTransaction(); session.saveOrUpdate(user); HibernateSessionFactory.commitTransaction(); } catch (HibernateException e) { HibernateSessionFactory.rollbackTransaction(); myLogger .error( " 新增使用者失敗 " , e); } finally { HibernateSessionFactory.closeSession(); } } public User getUserByID( int id) { User user = null ; Session session = HibernateSessionFactory.getSession(); try { //get 與 load 的差別 ? user = (User) session.get(User. class , new Integer(id)); } catch (HibernateException e) { myLogger .error( " 查詢使用者失敗 " , e); } finally { HibernateSessionFactory.closeSession(); } return user; } public static void main(String[] args) { User user = new User(); user.setName( " 張三 " ); user.setAge( new Integer(26)); UseDaoHBImpl manager = new UseDaoHBImpl(); // 增 manager.saveUser(user); // 查 User user1 = manager.getUserByID(1); if (user1 != null ){ user1.setName( " 李四 " ); // 改 manager.updateUser(user1); // 删 //manager.removeUserByID(user1.getId().intValue()); } } } |
3. 運作如上程式,操作成功的話,以資料庫就可以看到新插入的資料了。 4. 整個web應用程式的目錄結構如下:(我是在eclipse+MyEclispe下建構的)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIw1mYuQ3Ylp2byBHdzJXam91MlRXYuJXZilGavw1Zu9WeqF3LcRXZu9lbkN3Yfd2bsJ2Xw9CXzV2Zh1WavwFdl5mLuR2cj5yZvxmYtA3Lc9CX6MHc0RHaiojIsJye.bmp)
5. 本例源代碼: 6. Hibernate的核心接口: 所有的Hibernate應用中都會通路Hibernate的5個核心接口: 6.1. Configuration接口: 此接口的執行個體用于配置并且根啟動Hibernate。Hibernate通過Cofinguration執行個體來指定對象-關系映射檔案的位置或者動态配置Hibernate的屬性,然後建立SessionFactory執行個體。 6.2. SessionFactory接口: 一個SessionFactory執行個體對應一個資料存儲源。應用程式從SessionFactory中獲得Session執行個體。SessionFactory具有以下特點: 1. 線程安全,即同一個SessionFactory執行個體可以被應用的多個線程共享。 2. 它是重量級的,因為它需要一個很大的緩存,用來存放預定義的SQL語句以及映射中繼資料等。是以,如果應用程式隻通路一個資料庫,則隻需要建立一個SessionFactory執行個體。 6.3. Session接口: 應用最廣泛的接口。Session也被稱為持久化管理器,它提供了和持久化相關的操作:如添加、更新、删除、加載和查詢對象。session有以下特點: 1. 線程不安全,在設計軟體架構時,應該避免多個線程共享同一個Session執行個體。 2. Session執行個體是輕量級的,它的建立和銷毀不需要消耗太多的資源。 session有一個緩存,被稱為Hibernate的第一級緩存,它存放被目前工作單元加載的對象。 6.4. Transaction接口: Transaction接口是Hibernate的資料庫事務接口。它對底層的事務接口做了封裝,包括: JDBC API、JTA、CORBA。 Hibernate 應用可通過一緻的Transaction接口來聲明事務邊界,這有助于應用在不同的環境和容器中移植。 6.5. Query和Criteria接口: 它們是Hibernate的查詢接口,用于資料庫查詢對象以及控制執行查詢的過程。Query包裝了一個HQL(Hibernate Query Language)查詢語句,Criteria接口完全封裝了基于字元串形式的查詢語句,比Query更加面向對象,Cirteria接口擅長于執行動态查詢。