同一應用伺服器部署多個 Web 模組(如 bbs.war、blog.war),皆使用 Hibernate 且預設配置檔命名為 hibernate.cfg.xml。部署順序不同導致:
bbs.war → 正常blog.war → bbs 僅能讀取共用的在線用戶表,其餘映射(Forum.cfg.xml、Thread.cfg.xml)失效Hibernate 預設透過 Configuration().configure() 載入類路徑根目錄下的 hibernate.cfg.xml。多模組共用類加載器(如 Tomcat 共用 lib)時,先載入者勝出,後續模組的同名配置被忽略,導致映射檔未註冊。
| 方案 | 代碼示例 | 優點 | 缺點 |
|---|---|---|---|
| 1. 預設配置(有風險) | new Configuration().configure().buildSessionFactory() | 最簡潔 | 多模組衝突、無法隔離 |
| 2. 程式化註冊映射 | new Configuration().addClass(A.class).addClass(B.class).buildSessionFactory() | 無 XML 依賴 | 新增 POJO 需改 Java 代碼、違反 OCP |
| 3. 指定專屬配置檔(推薦) | new Configuration().configure("/moduleA.cfg.xml").buildSessionFactory() | 隔離性強、擴展性好、零代碼改動 | 需維護多份配置檔 |
src/main/resources/
├── hibernate-bbs.cfg.xml
├── hibernate-blog.cfg.xml
└── hibernate-common.cfg.xml
@Configuration
@PropertySource("classpath:hibernate-bbs.properties")
public class BbsHibernateConfig {
@Bean
public LocalSessionFactoryBean sessionFactory(DataSource dataSource) {
LocalSessionFactoryBean sf = new LocalSessionFactoryBean();
sf.setDataSource(dataSource);
sf.setConfigLocation(new ClassPathResource("hibernate-bbs.cfg.xml"));
sf.setPackagesToScan("com.example.bbs.entity");
sf.setHibernateProperties(hibernateProps());
return sf;
}
}
hibernate-common.cfg.xml 僅保留映射引用:
<hibernate-configuration>
<session-factory>
<mapping resource="com/example/bbs/entity/Forum.hbm.xml"/>
<mapping resource="com/example/bbs/entity/Thread.hbm.xml"/>
</session-factory>
</hibernate-configuration>
資料庫連線、方言、連接池等放入 .properties,透過 Spring @PropertySource 注入,實現配置與映射分離。
若專案已遷移至 JPA/Hibernate 5+,建議改用 persistence.xml + LocalContainerEntityManagerFactoryBean,天然支援多持久化單元隔離:
<persistence-unit name="bbsPU" transaction-type="JTA">
<jta-data-source>java:/jdbc/bbsDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
hibernate.cfg.xml 作為多模組專案的配置入口。.properties,映射檔保留於 XML,便於 Spring/容器統一管理。