Spring多数据源管理

来源:互联网 发布:win10平板优化精简版 编辑:程序博客网 时间:2024/05/13 04:12

Spring多数据源管理

环境

1. Tomcat 6.0.28

2. Spring 2.5, SpringSide 2.5

3. Hibernate

业务需求

1. Spring 管理多个数据源,针对通应用有效促进数据库分库,分用户

2. 分布式事务控制

3. 通过JNDI来获取数据源,程序员无需关系数据库相关配置

4. 抽取低层框架,用户权限集中管理

步骤

Tomcat配置

1. Tomcat有两种配置数据源的方式,

 第一种:全局数据库连接池,

 1. CATALINA_HOME/conf/context.xml, 这种称为全局资源,可以配置多个,推荐使用。

<Resource name="jdbc/ghlf"
auth="Container"
type="javax.sql.XADataSource"
factory="org.objectweb.jotm.datasource.DataSourceFactory"
password="admin"
username="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/ghlf"
maxActive="100"
maxIdle="30"  
maxWait="5000"
/>


 2. CATALINA_HOME/conf/server.xml, 这种可以看成是通过管理界面来配置的数据库连接池。
<Resource name="jdbc/mydb" type="javax.sql.DataSource"
 username="bmgis" password="bmgis"
 driverClassName="oracle.jdbc.driver.OracleDriver"
 url="jdbc:oracle:thin:@localhost:1521:mydb"
 maxIdle="2" maxWait="5000" maxActive="4"/>


 第二种:局部数据库连接池,CATALINA_HOME/webapps/META-INF/context.xml,


应用数据源引用

   
  <resource-ref> 
      <res-ref-name>jdbc/framework</res-ref-name> 
      <res-type>javax.sql.DataSource</res-type> 
      <res-auth>Container</res-auth> 
  </resource-ref>
    
  <resource-ref> 
      <res-ref-name>jdbc/ghlf</res-ref-name> 
      <res-type>javax.sql.DataSource</res-type> 
      <res-auth>Container</res-auth> 
  </resource-ref>


JNDI引用

在spring application.xml中

<bean id="dataSource_framework" class="org.springframework.jndi.JndiObjectFactoryBean" > 
     <property name="jndiName" value="java:comp/env/jdbc/framework"></property> 
 </bean>
 
   
 <bean id="dataSource_ghlf" class="org.springframework.jndi.JndiObjectFactoryBean" > 
     <property name="jndiName" value="java:comp/env/jdbc/ghlf"></property> 
 </bean>


配置sessionfactory

在应用中用到hibernate这个ORM框架,所以必须要将spring与hibernate集成

<bean id="sessionFactory_framework"
  class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="dataSource" ref="dataSource_framework" />
  <property name="namingStrategy">
   <bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">
     ${hibernate.dialect}
    </prop>
    <prop key="hibernate.show_sql">
     ${hibernate.show_sql}
    </prop>
    <prop key="hibernate.format_sql">
     ${hibernate.format_sql}
    </prop>
    <prop key="hibernate.cache.provider_class">
     org.hibernate.cache.EhCacheProvider
    </prop>
    <prop key="hibernate.cache.provider_configuration_file_resource_path">
     ${hibernate.ehcache_config_file}
    </prop>
   </props>
  </property>
  <property name="packagesToScan" value="cn.transfar._group.framework.entities,cn.transfar._group.framework.entities.*" />
 </bean>


   <bean id="sessionFactory_ghlf"
         class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
  <property name="dataSource" ref="dataSource_ghlf" />
  <property name="namingStrategy">
   <bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
  </property>
  <property name="hibernateProperties">
   <props>
    <prop key="hibernate.dialect">
     ${hibernate.dialect}
    </prop>
    <prop key="hibernate.show_sql">
     ${hibernate.show_sql}
    </prop>
    <prop key="hibernate.format_sql">
     ${hibernate.format_sql}
    </prop>
    <prop key="hibernate.cache.provider_class">
     org.hibernate.cache.EhCacheProvider
    </prop>
    <prop key="hibernate.cache.provider_configuration_file_resource_path">
     ${hibernate.ehcache_config_file}
    </prop>
   </props>
  </property>
  <property name="packagesToScan" value="cn.transfar._group._appname.entities,cn.transfar._group._appname.entities.*" />
 </bean>


事务管理

由于应用中用到的是annotation,事务控制全部在业务层去显示申明,并且在多数据源的环境中,jdbc本地事务是没有办法控制的,必须引用JTA全局事务,这样才能保证多个数据源的数据一致性。由此带来了新的问题,tomcat6是不支持JTA,不比jboss,和websphere等容器,所以必须借助额外的插件或者框架,这里以Jotm (java open transaction manager)为例。

   <bean id="jotm" class="org.springframework.transaction.jta.JotmFactoryBean"/>
 
    <!--  transaction manager definition-->
 <bean id="transactionManager"  class="org.springframework.transaction.jta.JtaTransactionManager">
      <property name="userTransaction" ref="jotm" />
 </bean>
   
    <!-- auto manage the transaction -->
 <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />


OpensessionInView

必须为多个数据源开启OpenSessionInView模式,这样在lazycelue环境中合理的管理会话,当然这种模式提供了多个配置支持

<filter>
  <filter-name>hibernateOpenSessionInViewFilterFramework</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
   <init-param>
            <param-name>excludeSuffixs</param-name>
            <param-value>js,css,jpg,gif</param-value>
        </init-param>
        <init-param>     
               <param-name>sessionFactoryBeanName</param-name>
            <param-value>sessionFactory_framework</param-value>  
        </init-param>  
 </filter>
 
 
 <filter>
  <filter-name>hibernateOpenSessionInViewFilterGHLF</filter-name>
  <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
  
   <init-param>
            <param-name>excludeSuffixs</param-name>
            <param-value>js,css,jpg,gif</param-value>
        </init-param>
        <init-param>     
               <param-name>sessionFactoryBeanName</param-name>
            <param-value>sessionFactory_ghlf</param-value>  
        </init-param>  
 </filter>



DAO实现指定数据源

由于springside集成了各种数据库操作方式,使用很方便,这里以他为例,

@Repository
public class FriendDAO extends HibernateDao<Friend, String>{

 
 @Override
 @javax.annotation.Resource(name="sessionFactory_ghlf")
 public void setSessionFactory(SessionFactory sessionFactory) {
  super.setSessionFactory(sessionFactory);
 }
 
}


分析

经过上面的配置基本可以运行,但是经过测试发现还有如下问题待解决:

1. JTA事务在异常的时候未能回滚

2. lazy加载存在问题

解决方案

1. 经过问题的错误及排查,可以肯定的是在数据元的配置上面,可能需要我们关注这两者的差别DataSource 和XADataSource, 前者在JTA环境下确实没有办法管理JTA事务,后者在JTA上面才支持事务,由此我们必须要启用XADataSource。

<Resource name="jdbc/ghlf"
auth="Container"
type="javax.sql.XADataSource"
factory="org.objectweb.jotm.datasource.DataSourceFactory"
password="admin"
username="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://127.0.0.1:3306/ghlf"
maxActive="100"
maxIdle="30"  
maxWait="5000"
/>


2. lazy加载问题出现主要是因为我们使用了spring-security来做权限管理,由此带来配置问题规范问题,我们前端主要用到的框架如下: structs,spring-security ,openSessionInView,siteMap,因此这几个的初始配置顺序是要考虑的。

<filter-mapping>
  <filter-name>encodingFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 
 <filter-mapping>
  <filter-name>hibernateOpenSessionInViewFilterFramework</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 
 <filter-mapping>
  <filter-name>hibernateOpenSessionInViewFilterGHLF</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

    <filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>
 
 <filter-mapping>
        <filter-name>sitemesh</filter-name>
        <url-pattern>*.action</url-pattern>
        <url-pattern>*.jsp</url-pattern>
    </filter-mapping>
   
 
 <filter-mapping>
  <filter-name>struts2Filter</filter-name>
  <url-pattern>*.action</url-pattern>
  <dispatcher>REQUEST</dispatcher>
  <dispatcher>FORWARD</dispatcher>
 </filter-mapping>


0 0
原创粉丝点击