Hibernate簡介
Hibernate是一個Java對象映射關(guān)系的解決方案的ORM(Object-Relational Mapping)框架耳峦,是一個開源持久框架,由
Gavin King
于2001年創(chuàng)建榛泛。為Java應(yīng)用提供強大的、高性能對象持久化和查詢服務(wù)。Hibernate將Java類映射到數(shù)據(jù)庫表叉橱,將Java數(shù)據(jù)類型映射到SQL數(shù)據(jù)類型,減輕了開發(fā)人員95%的數(shù)據(jù)持久性相關(guān)的編程任務(wù)者蠕。
Hibernate位于傳統(tǒng)的Java對象和數(shù)據(jù)庫服務(wù)器之間窃祝,基于適當(dāng)?shù)?code>O/R機制和模式來處理持久化這些對象的所有工作。
Hibernate的優(yōu)勢
- Hibernate通過XML配置文件將Java類映射到數(shù)據(jù)庫表踱侣,而不需要編寫任何代碼粪小。
- 提供簡單的API,用于直接存儲和檢索數(shù)據(jù)庫中的Java對象。
- 如果數(shù)據(jù)庫或任何表中有更改抡句,只需要修改XML文件探膊。
- 提取我們不熟悉的SQL類型,并提供我們熟悉的Java對象待榔。
- Hibernate不需要應(yīng)用府服務(wù)器來操作逞壁。
- 操作復(fù)雜關(guān)聯(lián)的數(shù)據(jù)庫對象。
- 使用智能抓取策略簡化數(shù)據(jù)庫操作。
- 提供簡單的數(shù)據(jù)查詢腌闯。
Hibernate支持的數(shù)據(jù)庫
Hibernate幾乎支持所有的關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(RDBMS),支持的數(shù)據(jù)庫如下所示:
- HSQL Database Engine
- DB2/NT
- MySQL
- PostgreSQL
- FrontBase
- Oracle
- Microsoft SQL Server Database
- Sybase SQL Server
- nformix Dynamic Server
Hibernate架構(gòu)
Hibernate架構(gòu)是分層的袭灯,所以我們不需要知道底層的API,Hibernate利用數(shù)據(jù)庫和配置數(shù)據(jù)向我們的應(yīng)用程序提供持久性服務(wù)(和持久性對象)绑嘹。
下圖是Hibernate應(yīng)用結(jié)構(gòu)體系簡要視圖:
下圖是Hibernate應(yīng)用結(jié)構(gòu)體系詳細(xì)視圖稽荧,包含了幾個重要的核心類:
- Hibernate使用各種現(xiàn)有的Java API,如
JDBC
,JTA
,JNDI
工腋。
JDBC
提供了關(guān)系數(shù)據(jù)庫通用的功能抽象層姨丈,所有具有JDBC
驅(qū)動程序的數(shù)據(jù)庫都被Hibernate
支持。
JTA
和JNDI
允許Hibernate
與J2EE服務(wù)器集成擅腰。
Hibernate應(yīng)用結(jié)構(gòu)體系主要類對象
Configuration Object
Configuration Object
是我們在Hibernate應(yīng)用程序中創(chuàng)建的第一個Hibernate對象蟋恬,通常在應(yīng)用程序初始化時且只創(chuàng)建一次。它是Hibernate所需要的配置和屬性文件趁冈。Configuration對象提供兩個關(guān)鍵組件:
-
Database Connection:通過Hibernate支持的一個或多個配置文件來處理歼争。
hibernate.properties
,hibernate.cfg.xml
。 - Class Mapping Setup:這個組件用于Java類和數(shù)據(jù)庫表之間創(chuàng)建連接渗勘。
SessionFactory Object
Configuration Object
用于創(chuàng)建一個SessionFactory Obejct
沐绒,該對象使用提供的配置文件為應(yīng)用程序配置Hibernate
,并允許實例化一個Session
對象旺坠。SessionFactory
是線程安全對象
,供應(yīng)用程序的所有線程使用乔遮。
SessionFactory
是重量級對象。因此通常在應(yīng)用程序啟動期間創(chuàng)建并保留供以后使用取刃。
每個數(shù)據(jù)庫都需要使用一個單獨的配置文件創(chuàng)建一個SessionFactory
對象蹋肮。如果使用多個數(shù)據(jù)庫,則必須創(chuàng)建多個SessionFactory
對象璧疗。
Session(會話) Object
Session(會話)
用于獲取與數(shù)據(jù)庫的物理連接坯辩,Session對象是輕量級的,并且是每當(dāng)需要與數(shù)據(jù)庫進(jìn)行交互時才會被實例化崩侠。持久化對象通過Session對象進(jìn)行保存和檢索漆魔。
Session對象不應(yīng)該長時間保持打開,因為他們通常不是線程安全的啦膜,所以應(yīng)該根據(jù)業(yè)務(wù)需求創(chuàng)建和銷毀它們有送。
Transaction(事務(wù)) Object
事務(wù)Transaction
代表與數(shù)據(jù)庫的工作單元,大多數(shù)關(guān)系型數(shù)據(jù)庫都支持事務(wù)功能僧家。Hibernate中的事務(wù)由底層事務(wù)管理器和事務(wù)(來自JDBC和JTA)處理雀摘。
這是一個可選對象,Hibernate應(yīng)用程序可以選擇不使用此接口八拱,而選擇在自己的應(yīng)用程序代碼中管理事務(wù)阵赠。
Query Object
查詢Query
對象使用SQL或者Hibernate查詢語言(Hibernate Query Language,HQL
)字符串從數(shù)據(jù)庫檢索數(shù)據(jù)并創(chuàng)建對象涯塔。Query實例用于綁定查詢參數(shù),限制查詢返回的結(jié)果數(shù)量清蚀,最后執(zhí)行查詢匕荸。
Criteria Object
條件對象用于創(chuàng)建和執(zhí)行面向?qū)ο蟮臉?biāo)準(zhǔn)查詢以檢索對象。
Hibernate 環(huán)境配置
該章主要介紹如何安裝Hibernate以及其它相關(guān)包來為Hibernate應(yīng)用程序準(zhǔn)備一個開發(fā)環(huán)境枷邪。本文將使用Mysql數(shù)據(jù)庫來演示Hibernate實例榛搔。
Hibernate下載
- 在windows上下載
.zip
文件,在Unix上下載.tz
文件东揣。 - 從http://www.hibernate.org/downloads下載最新版的Hibernate践惑。
- 下載完成之后進(jìn)行解壓。
安裝Hibernate
下載完Hibernate之后嘶卧,只需要執(zhí)行以下兩個簡單的步驟即可尔觉。請確保正確的配置了CLASSPATH
環(huán)境變量,否則在編譯應(yīng)用程序時會出現(xiàn)問題芥吟。
Hibernate的依賴包
S.N. | Packages/Libraries |
---|---|
1 | dom4j - XML parsing www.dom4j.org/ |
2 | Xalan - XSLT Processor http://xml.apache.org/xalan-j/ |
3 | Xerces - The Xerces Java Parser http://xml.apache.org/xerces-j/ |
4 | cglib - Appropriate changes to Java classes at runtime http://cglib.sourceforge.net/ |
5 | log4j - Logging Faremwork http://logging.apache.org/log4j |
6 | Commons - Logging, Email etc. http://jakarta.apache.org/commons |
7 | SLF4J - Logging Facade for Java http://www.slf4j.org |
Hibernate配置
Hibernate需要提前知道在哪里可以找到定義的Java類和數(shù)據(jù)庫表相關(guān)聯(lián)的映射信息侦铜。Hibernate還需要一組與數(shù)據(jù)庫和其它相關(guān)參數(shù)相關(guān)的配置設(shè)置。所有這些信息通常作為標(biāo)準(zhǔn)java屬性文件hibernate.properties
或者名為hibernate.cfg.xml
的XML文件提供钟鸵。
Hibernate屬性
以下是在獨立情況下為一個數(shù)據(jù)庫配置所需要的重要屬性列表:
S.N. | Properties and Description |
---|---|
1 |
hibernate.dialect :此屬性使Hibernate為選定的數(shù)據(jù)庫生成適當(dāng)?shù)腟QL |
2 |
hibernate.connection.driver_class :JDBC驅(qū)動程序類 |
3 |
hibernate.connection.url :數(shù)據(jù)庫實例的JDBC URL |
4 |
hibernate.connection.username :數(shù)據(jù)庫用戶名 |
5 |
hibernate.connection.password :數(shù)據(jù)庫密碼 |
6 |
hibernate.connection.pool_size :限制在Hibernate數(shù)據(jù)庫連接池中的等待連接數(shù) |
7 |
hibernate.connection.autocommit :允許JDBC連接自動提交 |
如果隨著應(yīng)用服務(wù)器和JNDI使用同一個服務(wù)器钉稍,則還需要配置以下屬性:
S.N. | Properties and Description |
---|---|
1 |
hibernate.connection.datasource :在應(yīng)用服務(wù)器中定義的JNDI名稱 |
2 |
hibernate.jndi.class :JNDI的InitialContext類 |
3 |
hibernate.jndi.<JNDIpropertyname> : |
4 |
hibernate.jndi.url :提供JNDI的url |
5 |
hibernate.connection.username :數(shù)據(jù)庫用戶名 |
6 |
hibernate.connection.password :數(shù)據(jù)庫密碼 |
Hibernate和Mysql數(shù)據(jù)庫
MySQL
是目前最流行的開源數(shù)據(jù)庫系統(tǒng)之一,下面我們創(chuàng)建一個hibernate.cfg.xml
配置文件携添,并將其放置于應(yīng)用程序類路徑的根目錄下嫁盲,必須確保已經(jīng)安裝MySQL
并保證已經(jīng)保證創(chuàng)建了可用的測試數(shù)據(jù)庫篓叶。
XML配置文件必須符合Hibernate 3 Configuration DTD烈掠,該文件可從http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd獲得。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume test is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://localhost/test
</property>
<property name="hibernate.connection.username">
root
</property>
<property name="hibernate.connection.password">
root123
</property>
<!-- List of XML mapping files -->
<mapping resource="Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
下表是各類數(shù)據(jù)庫的屬性類型(Dialect Property
)列表:
Database | Dialect Property |
---|---|
DB2 | org.hibernate.dialect.DB2Dialect |
HSQLDB | org.hibernate.dialect.HSQLDialect |
HypersonicSQL | org.hibernate.dialect.HSQLDialect |
Informix | org.hibernate.dialect.InformixDialect |
Ingres | org.hibernate.dialect.IngresDialect |
Interbase | org.hibernate.dialect.InterbaseDialect |
Microsoft SQL Server 2000 | org.hibernate.dialect.SQLServerDialect |
Microsoft SQL Server 2005 | org.hibernate.dialect.SQLServer2005Dialect |
Microsoft SQL Server 2008 | org.hibernate.dialect.SQLServer2008Dialect |
MySQL | org.hibernate.dialect.MySQLDialect |
Oracle (any version) | org.hibernate.dialect.OracleDialect |
Oracle 11g | org.hibernate.dialect.Oracle10gDialect |
Oracle 10g | org.hibernate.dialect.Oracle10gDialect |
Oracle 9i | org.hibernate.dialect.Oracle9iDialect |
PostgreSQL | org.hibernate.dialect.PostgreSQLDialect |
Progress | org.hibernate.dialect.ProgressDialect |
SAP DB | org.hibernate.dialect.SAPDBDialect |
Sybase | org.hibernate.dialect.SybaseDialect |
Sybase Anywhere | org.hibernate.dialect.SybaseAnywhereDialect |
Hibernate實例
創(chuàng)建POJO類
- 首先缸托,我們創(chuàng)建
Java POJO類
左敌,這取決于將被持久化到數(shù)據(jù)庫的應(yīng)用程序,生成getXXX()
和setXXX()
方法俐镐,使其成為JavaBeans
兼容類矫限。 - POJO(java普通對象)是一種java對象,它不擴展或?qū)崿F(xiàn)一些EJB框架分別需要的一些專門的類或接口佩抹。所有正常的Java對象都是POJO叼风。
- 當(dāng)你設(shè)計一個要被Hibernate持久化的類時,提供符合JavaBeans的代碼以及一個在Employee類中像id屬性一樣用作索引的屬性很重要棍苹。
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
public Employee() {}
public Employee(String fname, String lname, int salary) {
this.firstName = fname;
this.lastName = lname;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName( String first_name ) {
this.firstName = first_name;
}
public String getLastName() {
return lastName;
}
public void setLastName( String last_name ) {
this.lastName = last_name;
}
public int getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
創(chuàng)建數(shù)據(jù)庫表
第二步无宿,我們需要在數(shù)據(jù)庫中創(chuàng)建一張表,將表對應(yīng)我們需要持久化的每一個對象枢里,根據(jù)上面的java類我們創(chuàng)建下面這樣一個表“
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
創(chuàng)建配置映射文件
接下來我們需要創(chuàng)建一個配置文件孽鸡,說明Hibernate如何將定義的類映射至數(shù)據(jù)庫表蹂午。
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Employee" table="EMPLOYEE">
<meta attribute="class-description">
This class contains the employee detail.
</meta>
<id name="id" type="int" column="id">
<generator class="native"/>
</id>
<property name="firstName" column="first_name" type="string"/>
<property name="lastName" column="last_name" type="string"/>
<property name="salary" column="salary" type="int"/>
</class>
</hibernate-mapping>
我們應(yīng)該把映射文件保存為<classname>.hbm.xml
格式的文件。上面文件保存為Employee.hbm.xml
彬碱。
- 映射文件是一個XML格式的文檔豆胸。
<hibernate-mapping>
作為包含所有<class>
元素的根元素。 -
<class>
元素用于定義從java類到數(shù)據(jù)庫表的特定映射巷疼。java類名稱
使用使用類元素的name屬性
指定晚胡,并且使用table
屬性指定數(shù)據(jù)庫表名稱。 -
<meta>
元素是可選元素嚼沿,用于創(chuàng)建類描述搬泥。 -
<id>
是將類中的唯一ID元素映射到數(shù)據(jù)庫表的主鍵。id元素中的name屬性引用類中的屬性伏尼,cloumn屬性引用數(shù)據(jù)庫表中的列忿檩。type屬性保存hibernate映射類型,此映射類型將從Java轉(zhuǎn)換成SQL數(shù)據(jù)類型爆阶。 - id元素中的
<generator>
屬性用于自動生成主鍵值燥透,設(shè)置class的屬性值為native
,讓hibernate選擇identity
辨图,sequence
,hilo
算法來創(chuàng)建主鍵班套,這取決于底層數(shù)據(jù)庫的能力。 -
<property>
元素用于將Java類屬性映射到數(shù)據(jù)庫表中的列故河。元素的name屬性引用類中的屬性吱韭,cloumn屬性引用數(shù)據(jù)庫表中的列。type屬性保存hibernate映射類型鱼的,此映射類型將從Java類型轉(zhuǎn)換成SQL數(shù)據(jù)類型理盆。
創(chuàng)建應(yīng)用類(java class)
完成了以上步驟后,我們來創(chuàng)建一個應(yīng)用文件來測試一下我們的配置凑阶。
import java.util.List;
import java.util.Date;
import java.util.Iterator;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try{
factory = new Configuration().configure().buildSessionFactory();
}catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
}
ManageEmployee ME = new ManageEmployee();
/* 添加一些employee對象到數(shù)據(jù)庫表中*/
Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
Integer empID3 = ME.addEmployee("John", "Paul", 10000);
/* 列出所有employee對象 */
ME.listEmployees();
/* 修改 */
ME.updateEmployee(empID1, 5000);
/* 從數(shù)據(jù)庫中刪除 */
ME.deleteEmployee(empID2);
/* 列出所有對象s */
ME.listEmployees();
}
/* 向數(shù)據(jù)庫中添加employee對象的方法 */
public Integer addEmployee(String fname, String lname, int salary){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employeeID = (Integer) session.save(employee);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
return employeeID;
}
/* 列出所有employee對象的方法 */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator =
employees.iterator(); iterator.hasNext();){
Employee employee = (Employee) iterator.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
}
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
/* 修改employee對象的方法 */
public void updateEmployee(Integer EmployeeID, int salary ){
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
Employee employee =
(Employee)session.get(Employee.class, EmployeeID);
employee.setSalary( salary );
session.update(employee);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
/* 刪除employee對象的方法 */
public void deleteEmployee(Integer EmployeeID){
Session session = factory.openSession();
Transaction tx = null;
try{
tx = session.beginTransaction();
Employee employee =
(Employee)session.get(Employee.class, EmployeeID);
session.delete(employee);
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
}
}
編譯和執(zhí)行
編譯和執(zhí)行的步驟(請確保正確配置了環(huán)境變量):
- 創(chuàng)建
hibernate.cfg.xml
配置文件猿规。 - 創(chuàng)建
Employee.hbm.xml
映射文件。 - 創(chuàng)建
Employee.java
文件宙橱,并編譯它姨俩。 - 創(chuàng)建如上所示的
ManageEmployee.java
文件,并執(zhí)行編譯师郑。 - 執(zhí)行
ManageEmployee.class
文件环葵,運行程序。