# 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
##
## 8.2? 集成Hibernate3
Hibernate是全自動的ORM框架,能自動為對象生成相應SQL并透明的持久化對象到數據庫。
**Spring2.5+版本支持Hibernate 3.1+版本,不支持低版本,Spring3.0.5版本提供對Hibernate 3.6.0 Final版本支持。**
### 8.2.1? 如何集成
Spring通過使用如下Bean進行集成Hibernate:
* LocalSessionFactoryBean :用于支持XML映射定義讀取:
configLocation和configLocations:用于定義Hibernate配置文件位置,一般使用如classpath:hibernate.cfg.xml形式指定;
mappingLocations :用于指定Hibenate映射文件位置,如chapter8/hbm/user.hbm.xml;
hibernateProperties:用于定義Hibernate屬性,即Hibernate配置文件中的屬性;
dataSource:定義數據源;
hibernateProperties、dataSource用于消除Hibernate配置文件,因此如果使用configLocations指定配置文件,就不要設置這兩個屬性了,否則會產生重復配置。推薦使用dataSource來指定數據源,而使用hibernateProperties指定Hibernate屬性。
* AnnotationSessionFactoryBean:用于支持注解風格映射定義讀取,該類繼承LocalSessionFactoryBean并額外提供自動查找注解風格配置模型的能力:
annotatedClasses:設置注解了模型類,通過注解指定映射元數據。
packagesToScan:通過掃描指定的包獲取注解模型類,而不是手工指定,如“cn.javass.**.model”將掃描cn.javass包及子包下的model包下的所有注解模型類。
接下來學習一下Spring如何集成Hibernate吧:
**1、準備jar包:**
首先準備Spring對ORM框架支持的jar包:
+ org.springframework.orm-3.0.5.RELEASE.jar? //提供對ORM框架集成
下載hibernate-distribution-3.6.0.Final包,獲取如下Hibernate需要的jar包:
+ hibernate3.jar?????????????????????? //核心包
+ lib\required\antlr-2.7.6.jar????????????? //HQL解析時使用的包
+ lib\required\javassist-3.9.0.GA.jar?????? //字節碼類庫,類似于cglib
+ lib\required\commons-collections-3.1.jar? //對集合類型支持包,前邊測試時已經提供過了,無需再拷貝該包了
+ lib\required\dom4j-1.6.1.jar??????????? //xml解析包,用于解析配置使用
+ lib\required\jta-1.1.jar???????????????? //JTA事務支持包
+ lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar //用于支持JPA
下載slf4j-1.6.1.zip(http://www.slf4j.org/download.html),slf4j是日志系統門面(Simple Logging Facade for Java),用于對各種日志框架提供給一致的日志訪問接口,從而能隨時替換日志框架(如log4j、java.util.logging):
+ slf4j-api-1.6.1.jar???????? ?????//核心API
+ slf4j-log4j12-1.6.1.jar????????? //log4j實現
將這些jar包添加到類路徑中。
**2、對象模型定義,此處使用第七章中的UserModel:**
```
package cn.javass.spring.chapter7;
public class UserModel {
private int id;
private String myName;
//省略getter和setter
}
```
**3、Hibernate映射定義(chapter8/hbm/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="cn.javass.spring.chapter7.UserModel" table="test">
<id name="id" column="id"><generator class="native"/></id>
<property name="myName" column="name"/>
</class>
</hibernate-mapping>
```
**4、???數據源定義,此處使用第7章的配置文件,即“chapter7/applicationContext-resources.xml”文件。**
**5、???SessionFactory配置定義(chapter8/applicationContext-hibernate.xml):**
```
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/> <!-- 指定數據源 -->
<property name="mappingResources"> <!-- 指定映射定義 -->
<list>
<value>chapter8/hbm/user.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties"> <!--指定Hibernate屬性 -->
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
</props>
</property>
</bean>
```
**6、???獲取SessionFactory:**
```
package cn.javass.spring.chapter8;
//省略import
public class HibernateTest {
private static SessionFactory sessionFactory;
@BeforeClass
public static void beforeClass() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter8/applicationContext-hibernate.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
sessionFactory = ctx.getBean("sessionFactory", SessionFactory.class);
}
}
```
此處我們使用了chapter7/applicationContext-resources.xml定義的“dataSource”數據源,通過ctx.getBean("sessionFactory", SessionFactory.class)獲取SessionFactory。
**7、通過SessionFactory獲取Session對象進行創建和刪除表:**
```
@Before
public void setUp() {
//id自增主鍵從0開始
final String createTableSql = "create memory table test" + "(id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, " + "name varchar(100))";
sessionFactory.openSession().
createSQLQuery(createTableSql).executeUpdate();
}
@After
public void tearDown() {
final String dropTableSql = "drop table test";
sessionFactory.openSession().
createSQLQuery(dropTableSql).executeUpdate();
}
```
使用SessionFactory創建Session,然后通過Session對象的createSQLQuery創建本地SQL執行創建和刪除表。
**8、使用SessionFactory獲取Session對象進行持久化數據:**
```
@Test
public void testFirst() {
Session session = sessionFactory.openSession();
Transaction transaction = null;
try {
transaction = beginTransaction(session);
UserModel model = new UserModel();
model.setMyName("myName");
session.save(model);
} catch (RuntimeException e) {
rollbackTransaction(transaction);
throw e;
} finally {
commitTransaction(session);
}
}
```
```
private Transaction beginTransaction(Session session) {
Transaction transaction = session.beginTransaction();
transaction.begin();
return transaction;
}
private void rollbackTransaction(Transaction transaction) {
if(transaction != null) {
transaction.rollback();
}
}
private void commitTransaction(Session session) {
session.close();
}
```
使用SessionFactory獲取Session進行操作,必須自己控制事務,而且還要保證各個步驟不會出錯,有沒有更好的解決方案把我們從編程事務中解脫出來?Spring提供了HibernateTemplate模板類用來簡化事務處理和常見操作。
### 8.2.2?使用HibernateTemplate
HibernateTimplate模板類用于簡化事務管理及常見操作,類似于JdbcTemplate模板類,對于復雜操作通過提供HibernateCallback回調接口來允許更復雜的操作。
接下來示例一下HibernateTemplate的使用:
```
@Test
public void testHibernateTemplate() {
HibernateTemplate hibernateTemplate =
new HibernateTemplate(sessionFactory);
final UserModel model = new UserModel();
model.setMyName("myName");
hibernateTemplate.save(model);
//通過回調允許更復雜操作
hibernateTemplate.execute(new HibernateCallback<Void>() {
@Override
public Void doInHibernate(Session session)
throws HibernateException, SQLException {
session.save(model);
return null;
}});
}
```
通過new HibernateTemplate(sessionFactory) 創建HibernateTemplate模板類對象,通過調用模板類的save方法持久化對象,并且自動享受到Spring管理事務的好處。
而且HibernateTemplate 提供使用HibernateCallback回調接口的方法execute用來支持復雜操作,當然也自動享受到Spring管理事務的好處。
### 8.2.3? 集成Hibernate及最佳實踐
類似于JdbcDaoSupport類,Spring對Hibernate也提供了HibernateDaoSupport類來支持一致的數據庫訪問。HibernateDaoSupport也是DaoSupport實現:
接下來示例一下Spring集成Hibernate的最佳實踐:
**1、?定義Dao接口,此處使用cn.javass.spring.chapter7.dao. IUserDao:**
**2、?定義Dao接口實現,此處是Hibernate實現:**
```
package cn.javass.spring.chapter8.dao.hibernate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import cn.javass.spring.chapter7.UserModel;
import cn.javass.spring.chapter7.dao.IUserDao;
public class UserHibernateDaoImpl extends HibernateDaoSupport implements IUserDao {
private static final String COUNT_ALL_HQL = "select count(*) from UserModel";
@Override
public void save(UserModel model) {
getHibernateTemplate().save(model);
}
@Override
public int countAll() {
Number count = (Number) getHibernateTemplate().find(COUNT_ALL_HQL).get(0);
return count.intValue();
}
}
```
此處注意首先Hibernate實現放在dao.hibernate包里,其次實現類命名如UserHibernateDaoImpl,即×××HibernateDaoImpl,當然如果自己有更好的命名規范可以遵循自己的,此處只是提個建議。
**3、進行資源配置,使用resources/chapter7/applicationContext-resources.xml:**
**4、dao定義配置,在chapter8/applicationContext-hibernate.xml中添加如下配置:**
```
<bean id="abstractDao" abstract="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean id="userDao" class="cn.javass.spring.chapter8.dao.hibernate.UserHibernateDaoImpl" parent="abstractDao"/>
```
首先定義抽象的abstractDao,其有一個sessionFactory屬性,從而可以讓繼承的子類自動繼承sessionFactory屬性注入;然后定義userDao,且繼承abstractDao,從而繼承sessionFactory注入;我們在此給配置文件命名為applicationContext-hibernate.xml表示Hibernate實現。
**5、?最后測試一下吧(cn.javass.spring.chapter8\. HibernateTest):**
```
@Test
public void testBestPractice() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter8/applicationContext-hibernate.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
IUserDao userDao = ctx.getBean(IUserDao.class);
UserModel model = new UserModel();
model.setMyName("test");
userDao.save(model);
Assert.assertEquals(1, userDao.countAll());
}
```
和Spring JDBC框架的最佳實踐完全一樣,除了使用applicationContext-hibernate.xml代替了applicationContext-jdbc.xml,其他完全一樣。也就是說,DAO層的實現替換可以透明化。
### 8.2.4? Spring+Hibernate的CRUD
Spring+Hibernate CRUD(增刪改查)我們使用注解類來示例,讓我們看具體示例吧:
**1、首先定義帶注解的模型對象UserModel2:**
* 使用JPA注解@Table指定表名映射;
* 使用注解@Id指定主鍵映射;
* 使用注解@ Column指定數據庫列映射;
```
package cn.javass.spring.chapter8;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "test")
public class UserModel2 {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private int id;
@Column(name = "name")
private String myName;
//省略getter和setter
}
```
**2、?定義配置文件(chapter8/applicationContext-hibernate2.xml):**
**2.1、????????定義SessionFactory:**
此處使用AnnotationSessionFactoryBean通過annotatedClasses屬性指定注解模型來定義映射元數據;
```
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/> <!-- 1、指定數據源 -->
<property name="annotatedClasses"> <!-- 2、指定注解類 -->
<list><value>cn.javass.spring.chapter8.UserModel2</value></list>
</property>
<property name="hibernateProperties"><!-- 3、指定Hibernate屬性 -->
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.HSQLDialect
</prop>
</props>
</property>
</bean>
```
**2.2、定義HibernateTemplate?:**
```
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
```
**3、最后進行CURD測試吧:**
```
@Test
public void testCURD() {
String[] configLocations = new String[] {
"classpath:chapter7/applicationContext-resources.xml",
"classpath:chapter8/applicationContext-hibernate2.xml"};
ApplicationContext ctx = new ClassPathXmlApplicationContext(configLocations);
HibernateTemplate hibernateTemplate = ctx.getBean(HibernateTemplate.class);
UserModel2 model = new UserModel2();
model.setMyName("test");
insert(hibernateTemplate, model);
select(hibernateTemplate, model);
update(hibernateTemplate, model);
delete(hibernateTemplate, model);
}
private void insert(HibernateTemplate hibernateTemplate, UserModel2 model) {
hibernateTemplate.save(model);
}
private void select(HibernateTemplate hibernateTemplate, UserModel2 model) {
UserModel2 model2 = hibernateTemplate.get(UserModel2.class, 0);
Assert.assertEquals(model2.getMyName(), model.getMyName());
List<UserModel2> list = hibernateTemplate.find("from UserModel2");
Assert.assertEquals(list.get(0).getMyName(), model.getMyName());
}
private void update(HibernateTemplate hibernateTemplate, UserModel2 model) {
model.setMyName("test2");
hibernateTemplate.update(model);
}
private void delete(HibernateTemplate hibernateTemplate, UserModel2 model) {
hibernateTemplate.delete(model);
}
```
Spring集成Hibernate進行增刪改查是不是比Spring JDBC方式簡單許多,而且支持注解方式配置映射元數據,從而減少映射定義配置文件數量。
私塾在線原創內容 轉載請注明出處【[http://sishuok.com/forum/blogPost/list/0/2497.html](http://sishuok.com/forum/blogPost/list/0/2497.html#7214)】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC