Spring 與 Hibernate 的整合是 Java 企業級開發的經典組合。本文詳細梳理從傳統 hibernate.cfg.xml 遷移至 Spring 管理的完整過程,並說明關鍵配置項的作用與優化建議。
傳統模式下,Hibernate 透過 hibernate.cfg.xml 定義 SessionFactory:
<hibernate-configuration>
<session-factory>
<!-- 資料庫連線資訊 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/hibernate_test</property>
<property name="connection.username">root</property>
<property name="connection.password">password</property>
<!-- 連線池設定 (C3P0) -->
<property name="hibernate.c3p0.max_size">20</property>
<property name="hibernate.c3p0.min_size">1</property>
<property name="hibernate.c3p0.timeout">5000</property>
<property name="hibernate.c3p0.max_statements">100</property>
<!-- Hibernate 核心設定 -->
<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<property name="hbm2ddl.auto">update</property>
<property name="show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
<!-- 實體類映射 -->
<mapping class="com.example.entity.User"/>
<mapping class="com.example.entity.Person"/>
</session-factory>
</hibernate-configuration>
DataSource(支援 C3P0、Druid、HikariCP 等)packagesToScan 取代手動 <mapping>@Configuration
@EnableTransactionManagement
public class HibernateConfig {
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setDriverClassName("com.mysql.cj.jdbc.Driver");
ds.setJdbcUrl("jdbc:mysql://localhost:3306/hibernate_test?useSSL=false&serverTimezone=UTC");
ds.setUsername("root");
ds.setPassword("password");
ds.setMaximumPoolSize(20);
ds.setMinimumIdle(5);
return ds;
}
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
LocalSessionFactoryBean sfb = new LocalSessionFactoryBean();
sfb.setDataSource(dataSource);
sfb.setPackagesToScan("com.example.entity");
Properties props = new Properties();
props.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
props.setProperty("hibernate.hbm2ddl.auto", "update");
props.setProperty("hibernate.show_sql", "true");
props.setProperty("hibernate.format_sql", "true");
props.setProperty("hibernate.temp.use_jdbc_metadata_defaults", "false");
sfb.setHibernateProperties(props);
return sfb;
}
@Bean
public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
return new HibernateTransactionManager(sessionFactory);
}
}
| 配置項 | 用途 | 建議值 |
|---|---|---|
| hibernate.dialect | 資料庫方言,決定 SQL 生成策略 | MySQL5InnoDBDialect / MySQL8Dialect |
| hibernate.hbm2ddl.auto | 啟動時自動建表/更新結構 | 開發: update / 生產: validate/none |
| hibernate.show_sql | 控制台輸出執行 SQL | 開發 true / 生產 false |
| hibernate.format_sql | 格式化輸出 SQL 易讀性 | true |
| hibernate.temp.use_jdbc_metadata_defaults | 避免 MySQL 8+ LOB 建立報錯 | false |
傳統方式:手動建構 SessionFactory → openSession() → 手動管理事務
Spring 整合後:注入 SessionFactory → getCurrentSession() 獲取當前事務綁定 Session → @Transactional 聲明式事務管理
LocalSessionFactoryBean 與 HibernateTransactionManager,使用 @Qualifier 區分packagesToScan 路徑、實體類是否標註 @Entity@EnableTransactionManagement、方法非 private、同類內部調用繞過代理Spring 整合 Hibernate 5 的核心在於「資料源交給 Spring,SessionFactory 交給 Spring,事務交給 Spring」。透過 Java Config 替代 XML,配置更具類型安全、重構友善,並易於整合現代連線池(HikariCP)與監控工具。