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

SpringSide 2.0 多數據源架構實戰:從配置到事務管理的完整指南

     編輯:Java 相關知識

業務背景:數據分片與擴展性需求

為提升網站未來橫向擴展能力,採用數據分片架構,要求應用靈活訪問多個數據庫。若直接操作 JDBC 此乃小菜一碟,但 SpringSide 2.0 集成 Hibernate 後,數據訪問多通過配置實現,需重新梳理多數據源接入方案。

核心配置三部曲

1. 定義多數據源連接參數 (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

2. 配置多個 DataSource 與 SessionFactory (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>

3. 定義多事務管理器

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

DAO 層與 Service 層適配

實體類與 DAO 示例

// 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> { }

Service 注入指定 SessionFactory (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>

踩坑記:默認 Bean 名稱衝突與 OpenSessionInViewFilter 失效

  • 錯誤現象:啟動報錯「未找到 name 為 transactionManager 的 bean」,雖配置了 transactionManagerIndex,但框架內部仍尋找默認名稱。
  • 根因:SpringSide 多處硬編碼依賴默認 Bean 名稱(sessionFactory、transactionManager),多實例配置打破約定。
  • 連帶問題:OpenSessionInViewFilter 無法管理多 SessionFactory,導致懶加載失效。

臨時方案與長期規劃

為推進項目,暫將 YumDaysIndex 與 YumDaysContent 拆分為兩獨立項目部署。但此非長久之計:未來主從數據庫分離(主寫從讀)時,仍需在單項目內路由讀寫操作。建議深度定制 SpringSide 核心或遷移至 Spring Boot 原生多數據源支持(AbstractRoutingDataSource + 多 EntityManagerFactory),從架構層面徹底解決。

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