為提升網站未來橫向擴展能力,採用數據分片架構,要求應用靈活訪問多個數據庫。若直接操作 JDBC 此乃小菜一碟,但 SpringSide 2.0 集成 Hibernate 後,數據訪問多通過配置實現,需重新梳理多數據源接入方案。
jdbc.properties)jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.urlYumDaysIndex=jdbc:mysql://localhost:3306/YumDaysIndex?useUnicode=true&characterEncoding=utf8
jdbc.urlYumDays001=jdbc:mysql://localhost:3306/YumDays001?useUnicode=true&characterEncoding=utf8
dataAccessContext-hibernate.xml)關鍵點:每組 SessionFactory 僅 dataSource 屬性不同,annotatedClasses 指定各自管理的實體類。
<!-- 數據源 Index -->
<bean id="dataSourceYumDaysIndex" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}"/>
<property name="url" value="${jdbc.urlYumDaysIndex}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!-- SessionFactory Index -->
<bean id="sessionFactoryIndex" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSourceYumDaysIndex"/>
<property name="annotatedClasses">
<list>
<value>com.yumdays.model.Catalog</value>
<value>com.yumdays.model.Statistic</value>
</list>
</property>
<property name="hibernateProperties"> ... </property>
</bean>
<!-- 數據源 001 -->
<bean id="dataSourceYumDays001" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> ... </bean>
<!-- SessionFactory 001 -->
<bean id="sessionFactory001" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSourceYumDays001"/>
<property name="annotatedClasses"><list/></property>
<property name="hibernateProperties"> ... </property>
</bean>
<bean id="transactionManagerIndex" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactoryIndex"/>
</bean>
<bean id="transactionManager001" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory001"/>
</bean>
// Catalog.java
@Entity @Table(name="catalogs")
public class Catalog implements Serializable {
@Id @GenericGenerator(name="system-uuid", strategy="uuid")
public String getId() { return id; }
public String getName() { return name; }
// setter 省略
}
// CatalogManager.java
public class CatalogManager extends HibernateEntityDao<Catalog> { }
serviceContext.xml)<bean id="catalogManager" class="com.yumdays.service.CatalogManager">
<property name="sessionFactory" ref="sessionFactoryIndex"/>
</bean>
<bean id="statisticManager" class="com.yumdays.service.StatisticManager">
<property name="sessionFactory" ref="sessionFactoryIndex"/>
</bean>
applicationContext.xml)<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* *..service.CatalogManager.*(..))" advice-ref="txAdviceIndex"/>
<aop:advisor pointcut="execution(* *..service.StatisticManager.*(..))" advice-ref="txAdviceIndex"/>
</aop:config>
<tx:advice id="txAdviceIndex" transaction-manager="transactionManagerIndex">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
transactionManagerIndex,但框架內部仍尋找默認名稱。sessionFactory、transactionManager),多實例配置打破約定。OpenSessionInViewFilter 無法管理多 SessionFactory,導致懶加載失效。為推進項目,暫將 YumDaysIndex 與 YumDaysContent 拆分為兩獨立項目部署。但此非長久之計:未來主從數據庫分離(主寫從讀)時,仍需在單項目內路由讀寫操作。建議深度定制 SpringSide 核心或遷移至 Spring Boot 原生多數據源支持(AbstractRoutingDataSource + 多 EntityManagerFactory),從架構層面徹底解決。