Hibernate 與 Spring 的整合核心在於 applicationContext.xml 中正確配置 LocalSessionFactoryBean、DAO 注入 SessionFactory、聲明式事務管理。本文以 MyEclipse 反向工程生成代碼為基礎,逐步構建整合範例,涵蓋單向/雙向映射、事務代理、測試驗證全流程。
Spring 容器 ├─ LocalSessionFactoryBean (id=sessionFactory) ← 引用 hibernate.cfg.xml ├─ HibernateDaoSupport 子類 DAO (注入 sessionFactory) ├─ HibernateTransactionManager (綁定 sessionFactory) └─ TransactionProxyFactoryBean (目標 DAO + 事務屬性) → 事務代理
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC ...>
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.microsoft.jdbc.sqlserver.SQLServerDriver</property>
<property name="connection.url">jdbc:microsoft:sqlserver://127.0.0.1:1433;DatabaseName=manager</property>
<property name="connection.username">sa</property>
<property name="connection.password">wq</property>
<property name="dialect">org.hibernate.dialect.SQLServerDialect</property>
<!-- 只保留 Spring 管理的映射 -->
<mapping resource="springDao/Sstest.hbm.xml" />
</session-factory>
</hibernate-configuration>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- 1. SessionFactory -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml"/>
</bean>
<!-- 2. 目標 DAO (Spring 管理的 HibernateDaoSupport) -->
<bean id="SstestDAO" class="springDao.SstestDAO">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 3. 事務管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 4. 事務代理 (聲明式事務) -->
<bean id="SstestDAOProxy"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="proxyTargetClass" value="true"/> <!-- CGLIB 代理類而非介面 -->
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="SstestDAO"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop> <!-- 所有方法開啟事務 -->
</props>
</bean>
</beans>
package springDao;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import java.util.List;
public class SstestDAO extends HibernateDaoSupport {
public void save(Sstest transientInstance) {
getHibernateTemplate().save(transientInstance);
}
public void delete(Sstest persistentInstance) {
getHibernateTemplate().delete(persistentInstance);
}
public Sstest findById(Integer id) {
return getHibernateTemplate().get(Sstest.class, id);
}
public List findAll() {
return getHibernateTemplate().find("from Sstest");
}
// ... 其他查詢方法均委託給 HibernateTemplate
}
<!-- Sstest.hbm.xml -->
<hibernate-mapping>
<class name="springDao.Sstest" table="sstest" schema="dbo" catalog="manager">
<id name="id" type="java.lang.Integer">
<column name="id"/>
<generator class="increment"/>
</id>
<property name="username" type="java.lang.String">
<column name="username" length="10"/>
</property>
<property name="password" type="java.lang.String">
<column name="password" length="20"/>
</property>
</class>
</hibernate-mapping>
// Sstest.java
package springDao;
public class Sstest implements java.io.Serializable {
private Integer id;
private String username;
private String password;
// getter/setter 略
}
package org.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import springDao.Sstest;
import springDao.SstestDAO;
public class SpringDaoTest {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 使用事務代理 Bean
SstestDAO dao = (SstestDAO) ctx.getBean("SstestDAOProxy");
Sstest st = new Sstest();
st.setUsername("spring");
st.setPassword("spring");
dao.save(st); // 此時在事務中執行
System.out.println("保存成功,ID=" + st.getId());
}
}
hibernate.cfg.xml 連接數據庫。Hibernate Reverse Engineering → 勾選 Java Data Object, Hibernate Mapping, Java DAO → 生成基礎包 (如 hibernateDao)。applicationContext.xml 自動生成 sessionFactory Bean。HibernateDaoSupport 的 DAO (如 springDao 包)。hibernate.cfg.xml 中註釋掉第一次生成的映射,保留第二次的。LocalSessionFactoryBean 依賴 Hibernate 類。<mapping>。SstestDAOProxy 而非原始 SstestDAO,否則無事務。proxyTargetClass=true 要求類非 final、方法非 final、有無參構造器。現代 Spring (3.0+) 建議使用
@Transactional註解配合<tx:annotation-driven/>替代TransactionProxyFactoryBean,配置更簡潔、類型安全。本文方案適用於 Spring 2.x 維護項目或需理解底層代理原理的場景。