Hibernate入門
++YONG原創(chuàng),轉(zhuǎn)載請(qǐng)聲明
1. 應(yīng)用程序的分層體系結(jié)構(gòu):
1.1. 典型的三層結(jié)構(gòu):
1.1.1. 表示層:提供數(shù)據(jù)輸入、檢驗(yàn)與數(shù)據(jù)呈現(xiàn)的應(yīng)用程序組件。(GUI、web頁(yè)面)。就是與用戶打交道的UI界面。
1.1.2. 業(yè)務(wù)層:提供商業(yè)邏輯服務(wù)的應(yīng)用程序組件。
1.1.3. 數(shù)據(jù)層:負(fù)責(zé)存放和管理應(yīng)用的持久性業(yè)務(wù)數(shù)據(jù)的持久化存儲(chǔ)系統(tǒng)。(Database、XML),最常見(jiàn)的持久化存儲(chǔ)系統(tǒng)就是廣泛使用的關(guān)系數(shù)據(jù)庫(kù)。
1.2. 軟件層的特征:
1.2.1. 每個(gè)層由一組相關(guān)的類或組件構(gòu)成,共同完成特定的功能。
1.2.2. 層與層之間存在自上而下的依賴關(guān)系。即上層組件會(huì)訪問(wèn)下層組件的API,而下層組件不應(yīng)該依賴上層組件。如:表現(xiàn)層依賴于業(yè)務(wù)邏輯層,而業(yè)務(wù)邏輯層依賴于數(shù)據(jù)層。
1.2.3. 每個(gè)層對(duì)上層公開(kāi)API,封裝實(shí)現(xiàn)細(xì)節(jié)。當(dāng)某一層的實(shí)現(xiàn)發(fā)生改變,只要它的API不變,不會(huì)影響其他層的實(shí)現(xiàn)。
1.3. 軟件分層的優(yōu)點(diǎn):
1.3.1. 伸縮性強(qiáng):能支持更多的用戶。
1.3.2. 可維護(hù)性高:修改軟件的某一層的實(shí)現(xiàn),不會(huì)影響其他層。
1.3.3. 可擴(kuò)展性強(qiáng):增加新功能更容易,每個(gè)層中都有擴(kuò)展點(diǎn),不會(huì)打破應(yīng)用的整體框架。
1.3.4. 可重用性高:同一程序能滿足多種需求。
1.3.5. 可管理性高:工作、管理模塊化。
1.4. 四層結(jié)構(gòu):
由于數(shù)據(jù)存儲(chǔ)方式多樣,業(yè)務(wù)層不僅要負(fù)責(zé)業(yè)務(wù)邏輯的處理,還要跟數(shù)據(jù)層交互,提供對(duì)業(yè)務(wù)數(shù)據(jù)的CRUD操作(create、retrieve、update、delete)。為了把業(yè)務(wù)數(shù)據(jù)訪問(wèn)細(xì)節(jié)和業(yè)務(wù)邏輯分開(kāi),把業(yè)務(wù)數(shù)據(jù)訪問(wèn)作為單獨(dú)的持久層。因此目前流行的軟件分層結(jié)構(gòu)是:
1. 表示層:
層:業(yè)務(wù)邏輯層負(fù)責(zé)完成應(yīng)用程序的邏輯功能,包括調(diào)用持久層完成實(shí)體對(duì)象的存取、安全檢查,事務(wù)控制等。抽象出業(yè)務(wù)邏輯層的好處是將應(yīng)用程序的邏輯功能從表示層中剝離,這樣就能復(fù)用邏輯層的功能。此外,業(yè)務(wù)邏輯層也可以看作是對(duì)持久層的一個(gè)門面模式,簡(jiǎn)化表示層對(duì)這些邏輯功能的調(diào)用。
3. 持久層:封裝了業(yè)務(wù)數(shù)據(jù)訪問(wèn)細(xì)節(jié),為業(yè)務(wù)層提供了面向?qū)ο蟮腁PI。持久層負(fù)責(zé)實(shí)現(xiàn)所有的數(shù)據(jù)訪問(wèn)功能,它將上層傳入的數(shù)據(jù)寫(xiě)入到持久化存儲(chǔ)系統(tǒng)中,并根據(jù)上層的要求讀取或修改現(xiàn)有的數(shù)據(jù)。
4. 數(shù)據(jù)層:
1.5. 完善的持久層應(yīng)該達(dá)到以下目標(biāo):
l 代碼可重用性高,能夠完成所有的數(shù)據(jù)訪問(wèn)操作。
l 具有相對(duì)獨(dú)立性,當(dāng)持久層的實(shí)現(xiàn)細(xì)節(jié)發(fā)生變化,不會(huì)影響上層的實(shí)現(xiàn)。
2. ORM簡(jiǎn)介:
1. ORM(Object-Relation Mapping)對(duì)象-關(guān)系映射模式指的是在單個(gè)組件中負(fù)責(zé)所有實(shí)體域?qū)ο蟮某志没?,封裝數(shù)據(jù)訪問(wèn)的細(xì)節(jié)。
2. Hibernate就是一個(gè)開(kāi)源的ORM中間件。(官方網(wǎng)站: http://www.hibernate.org/)
3. Hibernate簡(jiǎn)介:
2001年未 Hibernate 第一個(gè)版本發(fā)表,2003年6月8日 Hibernate 2 發(fā)表,并于年未獲得 Jolt 2004 大獎(jiǎng),后被 JBOSS 收納而成為其子項(xiàng)目之一,2005年3月 Hibernate 3 正式發(fā)表,當(dāng)中有了一些重大的改變,本文使用的版本為Hibernate 3.2。
4. 配置 hibernate:
4.1. 準(zhǔn)備好所需的jar包:
到官方網(wǎng)站:
http://www.hibernate.org/6.html 下載(當(dāng)前版本:Hibernate Core 3.2.3GA ) hibernate包。解開(kāi)壓縮包。在lib目錄下找到以下hibernate應(yīng)用所必須的包(可以查看該目錄下的_README.txt文件來(lái)確定哪些包是必需的):
1. hibernate.jar :hibernate核心包。必需的。
2. antlr.jar :Hibernate使用ANTLR來(lái)產(chǎn)生查詢分析器,這個(gè)類庫(kù)在運(yùn)行環(huán)境下時(shí)也是必需的。
3. cglib.jar :CGLIB庫(kù),Hibernate用它來(lái)實(shí)現(xiàn)PO字節(jié)碼的動(dòng)態(tài)生成,非常核心的庫(kù),必需的jar包。
4. asm.jar :ASM字節(jié)碼庫(kù),cglib.jar包依賴的包。必需的jar包。
5. asm-attrs.jar :ASM字節(jié)碼庫(kù),cglib.jar包依賴的包。必需的jar包。
6. commons-collections.jar :Apache Commons包中的一個(gè),包含了一些Apache開(kāi)發(fā)的集合類,功能比java.util.*強(qiáng)大。必須使用的jar包。
7. commons-logging.jar :Apache Commons包中的一個(gè),包含了日志功能,必須使用的jar包。這個(gè)包本身包含了一個(gè)Simple Logger,但是功能很弱。在運(yùn)行的時(shí)候它會(huì)先在CLASSPATH找log4j,如果有,就使用log4j,如果沒(méi)有,就找JDK1.4帶的java.util.logging,如果也找不到就用Simple Logger。必需的。
8. ehcache.jar :Hibernate可以使用不同cache緩存工具作為二級(jí)緩存。EHCache是缺省的cache緩存工具。如果沒(méi)有其它的可選緩存工具,則為必需的。
9. jta.jar :JTA規(guī)范,當(dāng)Hibernate使用JTA的時(shí)候需要。必需的。
10. dom4j.jar :dom4j是一個(gè)Java的XML API,類似于jdom,用來(lái)讀寫(xiě)XML文件的。Hibernate使用dom4j解析XML配置文件和XML映射元文件。必需的。
11. log4j.jar :日志包,可選的。
把以上必需的jar放置到應(yīng)用程序的類路徑中(web應(yīng)用的WEB-INF/lib目錄下)。
4.2. 基本的Hibernate配置文件:
在WEB-INF/classes目錄下創(chuàng)建一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>
<!-- 數(shù)據(jù)庫(kù)連接設(shè)置 -->
<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>
<!--實(shí)際操作數(shù)據(jù)庫(kù)時(shí)是否顯示SQL -->
<property name="show_sql">true</property>
<!--將數(shù)據(jù)庫(kù)schema的DDL導(dǎo)出到數(shù)據(jù)庫(kù) -->
<!--property name="hibernate.hbm2ddl.auto">create </property!-->
<!-- 以下設(shè)置對(duì)象與數(shù)據(jù)庫(kù)表的映像文件 -->
......
</session-factory>
</hibernate-configuration>
5. 第一個(gè)Hibernate應(yīng)用程序:
5.1. 創(chuàng)建一個(gè)持久化類:
持久化類就是其實(shí)例要被持久化到數(shù)據(jù)庫(kù)中的類,通常都是實(shí)體域類,它是帶有一些屬性及屬性的getters、setters方法的POJO類:
package org.qiujy.demo;
/**
*User持久化類
*第一個(gè)Hibernate示例
*@authorAdministrator
*
*/
publicclass User {
private Integer id;
private String name;
private Integer age;
public User(){}
public Integer getAge() {
returnage;
}
publicvoid setAge(Integer age) {
this.age = age;
}
public Integer getId() {
returnid;
}
publicvoid setId(Integer id) {
this.id = id;
}
public String getName() {
returnname;
}
publicvoid setName(String name) {
this.name = name;
}
}
5.2. 準(zhǔn)備好數(shù)據(jù)庫(kù)表:
在MySQL中新增一個(gè)demo數(shù)據(jù)庫(kù),并建立user表:
CREATE TABLE user (
id INT(11) NOT NULL auto_increment PRIMARY KEY,
name VARCHAR(100) NOT NULL default '',
age INT
);
5.3. 創(chuàng)建對(duì)象-關(guān)系映射文件:
Hibernate需要知道怎樣去加載(load)和存儲(chǔ)(store)持久化類的對(duì)象。這正是Hibernate映射文件發(fā)揮作用的地方。映射文件告訴Hibernate應(yīng)該訪問(wèn)數(shù)據(jù)庫(kù)(database)里面的哪個(gè)表(table)以及應(yīng)該使用表里面的哪些字段(column)。
在持久化類所在的包的目錄下創(chuàng)建一名為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>
<!-- 以下設(shè)置對(duì)象與數(shù)據(jù)庫(kù)表的映像文件 -->
<mapping resource="org/qiujy/demo/User.hbm.xml" />
</session-factory>
5.5. 使用Hibernate API進(jìn)行持久化操作:
1. 創(chuàng)建一輔助類:由這個(gè)輔助類來(lái)創(chuàng)建一個(gè)線程安全的、全局的SessoinFactory,SessionFactory可以創(chuàng)建并打開(kāi)新的單線程的Session。
package org.qiujy.common;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
/**
* HibernateSession工廠
*/
public class HibernateSessionFactory {
/** Hibernate的配置文件hibernate.cfg.xml */
private static String CONFIG_FILE_LOCATION = "/hibernate.cfg.xml";
/** Session的線程本地變量 */
private static final ThreadLocal threadLocal = new ThreadLocal();
/** transaction的線程本地變量 */
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() {
}
/**
* 獲得一個(gè)線程本地化的Hibernate session實(shí)例
* @return Session
* @throws HibernateException
*/
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;
}
/**
* Rebuild hibernate session factory
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}
/**
* 關(guān)閉線程化的Hibernate session實(shí)例
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);
if (session != null) {
session.close();
}
}
/**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}
/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
HibernateSessionFactory.configFile = configFile;
sessionFactory = null;
}
/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}
/**
* 在本地session實(shí)例上開(kāi)啟事務(wù)
*/
public static void beginTransaction(){
Transaction tx = (Transaction)txThreadLocal.get();
if(tx == null){
tx = getSession().beginTransaction();
txThreadLocal.set(tx);
}
}
/**
* 在本地session實(shí)例上提交事務(wù)
*/
public static void commitTransaction(){
Transaction tx = (Transaction)txThreadLocal.get();
if(tx != null && !tx.wasCommitted() && !tx.wasRolledBack()){
tx.commit();
txThreadLocal.set(null);
}
}
/**
* 在本地session實(shí)例上回滾事務(wù)
*/
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;
publicclass UseDaoHBImpl {
privatestatic Logger myLogger = Logger.getLogger(UseDaoHBImpl.class);
/**
*新增一個(gè)用戶
*@paramuser 用戶對(duì)象
*/
publicvoid 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();
}
}
/**
*根據(jù)ID刪除該用戶對(duì)象
*@paramid用戶ID
*/
publicvoid 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();
}
}
/**
*更新用戶的信息
*@paramuser用戶對(duì)象
*/
publicvoid 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();
}
}
/**
*根據(jù)用戶ID查詢?cè)撚脩魧?duì)象
*@paramid 用戶ID
*@returnUser查詢成功返回該用戶對(duì)象,否則返回null
*/
public User getUserByID(int id) {
User user = null;
Session session = HibernateSessionFactory.getSession();
try {
//get與load的區(qū)別?
user = (User) session.get(User.class, new Integer(id));
} catch (HibernateException e) {
myLogger.error("查詢用戶失敗", e);
} finally {
HibernateSessionFactory.closeSession();
}
return user;
}
publicstaticvoid 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. 運(yùn)行如上程序,操作成功的話,以數(shù)據(jù)庫(kù)就可以看到新插入的數(shù)據(jù)了。
4. 整個(gè)web應(yīng)用程序的目錄結(jié)構(gòu)如下:(我是在eclipse+MyEclispe下構(gòu)建的)
5. 本例源代碼:
6. Hibernate的核心接口:
所有的Hibernate應(yīng)用中都會(huì)訪問(wèn)Hibernate的5個(gè)核心接口:
6.1. Configuration接口:
此接口的實(shí)例用于配置并且根啟動(dòng)Hibernate。Hibernate通過(guò)Cofinguration實(shí)例來(lái)指定對(duì)象-關(guān)系映射文件的位置或者動(dòng)態(tài)配置Hibernate的屬性,然后創(chuàng)建SessionFactory實(shí)例。
6.2. SessionFactory接口:
一個(gè)SessionFactory實(shí)例對(duì)應(yīng)一個(gè)數(shù)據(jù)存儲(chǔ)源。應(yīng)用程序從SessionFactory中獲得Session實(shí)例。SessionFactory具有以下特點(diǎn):
1. 線程安全,即同一個(gè)SessionFactory實(shí)例可以被應(yīng)用的多個(gè)線程共享。
2. 它是重量級(jí)的,因?yàn)樗枰粋€(gè)很大的緩存,用來(lái)存放預(yù)定義的SQL語(yǔ)句以及映射元數(shù)據(jù)等。所以,如果應(yīng)用程序只訪問(wèn)一個(gè)數(shù)據(jù)庫(kù),則只需要?jiǎng)?chuàng)建一個(gè)SessionFactory實(shí)例。
6.3. Session接口:
應(yīng)用最廣泛的接口。Session也被稱為持久化管理器,它提供了和持久化相關(guān)的操作:如添加、更新、刪除、加載和查詢對(duì)象。session有以下特點(diǎn):
1. 線程不安全,在設(shè)計(jì)軟件架構(gòu)時(shí),應(yīng)該避免多個(gè)線程共享同一個(gè)Session實(shí)例。
2. Session實(shí)例是輕量級(jí)的,它的創(chuàng)建和銷毀不需要消耗太多的資源。
session有一個(gè)緩存,被稱為Hibernate的第一級(jí)緩存,它存放被當(dāng)前工作單元加載的對(duì)象。
6.4. Transaction接口:
Transaction接口是Hibernate的數(shù)據(jù)庫(kù)事務(wù)接口。它對(duì)底層的事務(wù)接口做了封裝,包括:
JDBC API、JTA、CORBA。
Hibernate 應(yīng)用可通過(guò)一致的Transaction接口來(lái)聲明事務(wù)邊界,這有助于應(yīng)用在不同的環(huán)境和容器中移植。
6.5. Query和Criteria接口:
它們是Hibernate的查詢接口,用于數(shù)據(jù)庫(kù)查詢對(duì)象以及控制執(zhí)行查詢的過(guò)程。Query包裝了一個(gè)HQL(Hibernate Query Language)查詢語(yǔ)句,Criteria接口完全封裝了基于字符串形式的查詢語(yǔ)句,比Query更加面向?qū)ο螅珻irteria接口擅長(zhǎng)于執(zhí)行動(dòng)態(tài)查詢。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1814371