首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Hibernate 與 Spring 整合完整指南:從配置到事務代理的最佳實踐

     編輯:Java 相關知識

Hibernate 與 Spring 的整合核心在於 applicationContext.xml 中正確配置 LocalSessionFactoryBean、DAO 注入 SessionFactory、聲明式事務管理。本文以 MyEclipse 反向工程生成代碼為基礎,逐步構建整合範例,涵蓋單向/雙向映射、事務代理、測試驗證全流程。

整合架構圖

Spring 容器
├─ LocalSessionFactoryBean (id=sessionFactory) ← 引用 hibernate.cfg.xml
├─ HibernateDaoSupport 子類 DAO (注入 sessionFactory)
├─ HibernateTransactionManager (綁定 sessionFactory)
└─ TransactionProxyFactoryBean (目標 DAO + 事務屬性) → 事務代理

關鍵配置文件

1. hibernate.cfg.xml (數據源與映射)

<?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>

2. applicationContext.xml (核心整合點)

<?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>

DAO 實現 (繼承 HibernateDaoSupport)

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());
    }
}

MyEclipse 反向工程關鍵步驟

  1. 先導入 Hibernate 庫,建立 hibernate.cfg.xml 連接數據庫。
  2. 右鍵表 → Hibernate Reverse Engineering → 勾選 Java Data Object, Hibernate Mapping, Java DAO → 生成基礎包 (如 hibernateDao)。
  3. 再導入 Spring 庫,applicationContext.xml 自動生成 sessionFactory Bean。
  4. 第二次反向工程:同樣表,但 DAO Type 選 Spring DAO (而非 Basic DAO),生成繼承 HibernateDaoSupport 的 DAO (如 springDao 包)。
  5. 在 hibernate.cfg.xml 中註釋掉第一次生成的映射,保留第二次的。
  6. 添加事務管理器與代理配置 (如上)。

常見坑點提示

  • Jar 包順序:Hibernate 庫必須先於 Spring 導入,因 LocalSessionFactoryBean 依賴 Hibernate 類。
  • 映射衝突:同一實體不可重複映射,第二次生成後務必註釋第一次的 <mapping>。
  • 事務邊界:測試時必須獲取 SstestDAOProxy 而非原始 SstestDAO,否則無事務。
  • CGLIB 限制:proxyTargetClass=true 要求類非 final、方法非 final、有無參構造器。

現代 Spring (3.0+) 建議使用 @Transactional 註解配合 <tx:annotation-driven/> 替代 TransactionProxyFactoryBean,配置更簡潔、類型安全。本文方案適用於 Spring 2.x 維護項目或需理解底層代理原理的場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved