您的位置:首页 > 编程语言 > Java开发

spring无事务的数据源切换,和带事务的数据源切换

2016-04-07 11:40 495 查看
最近在配置spring框架时需要使用多数据源,其中遇到一些问题,特此记录

无事务数据源切换

http://blog.csdn.net/shadowsick/article/details/8878448 
主要说一下带事务数据源切换的配置

首先在spring-database.xml中配置两个数据源(默认数据源),和应用的切面

<!-- backend数据源  -->
<bean id="dataSourceBackend" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="${backend.url}"></property>
<property name="username" value="${backend.username}"></property>
<property name="password" value="${backend.password}"></property>
</bean>
<!-- pi数据源  -->
<bean id="dataSourcePIDB" class="org.springframework.jdbc.datasource.DriverManagerDataSource" >
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="${pi.url}"></property>
<property name="username" value="${pi.username}"></property>
<property name="password" value="${pi.password}"></property>
</bean>

<!-- 多数据源配置  -->
<bean id="dynamicDataSource" class="com.test.base.dao.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry value-ref="dataSourceBackend" key="dataSourceBackend"></entry>
<entry value-ref="dataSourcePIDB" key="dataSourcePIDB"></entry>
</map>
</property>  <!--默认数据源-->
<property name="defaultTargetDataSource" ref="dataSourceBackend">
</property>
</bean>
<aop:config><!--切面-->
<aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor">
<aop:pointcut id="daoBackend" expression="execution(* com.test.backend.service.ReportService.*(..))" />
<aop:before pointcut-ref="daoBackend" method="setdataSourceBackend" />

<aop:pointcut id="daopidb" expression="execution(* com.test.backend.service.MacIpService.*(..))" />
<aop:before pointcut-ref="daopidb" method="setdataSourcePIDB" /><!--切面before调用的方法-->
<aop:after pointcut-ref="daopidb" method="cleardataSource" /><!--切面after调用的方法-->

</aop:aspect>
</aop:config>


多数据源route类

public class DynamicDataSource extends AbstractRoutingDataSource{

@Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getCustomerType();
}

}


数据源内容配置类

public class DatabaseContextHolder {

private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();

public static void setCustomerType(String customerType) {
contextHolder.set(customerType);
}

public static String getCustomerType() {
return contextHolder.get();
}

public static void clearCustomerType() {
contextHolder.remove();
}

}
@Component
public class DataSourceInterceptor {

public void setdataSourceBackend(JoinPoint jp) {
DatabaseContextHolder.setCustomerType("dataSourceBackend");
}
public void setdataSourcePIDB(JoinPoint jp) {
DatabaseContextHolder.setCustomerType("dataSourcePIDB");
}

public void cleardataSource(JoinPoint jp){
DatabaseContextHolder.clearCustomerType();
}

}


上边xml中配置的 dataSourceInterceptor 会找到class DataSourceInterceptor,并执行set**方法和clear**方法,并设置CustomerType(数据源)给contextHolder,以便于

在determineCurrentLookupKey方法中可以获得到改变后的数据源.

然后是事务的配置

在spring-application.xml中

加上如下配置

</pre></p><p><pre name="code" class="html"> <import resource="spring-database.xml"/>

<!-- 配置SessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dynamicDataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.autoReconnect">true</prop>
<prop key="hibernate.connection.autocommit">true</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
<property name="packagesToScan" value="com.test.backend.entity" />
</bean>

<!-- 配置一个事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>

<!-- 事务管理  start-->
<tx:annotation-driven transaction-manager="transactionManager" />

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
<tx:method name="del*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
<tx:method name="find*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
<tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
</tx:attributes>
</tx:advice>

<aop:config>
<!-- 实施事务 -->
<aop:pointcut id="txPointcut" expression="execution(* com.test.backend.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" />
</aop:config>
<!-- 事务管理  end-->

在web.xml中加上了spring管理hibernate的session

<filter>
<filter-name>openSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>openSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

注意:加上事务时候,我这的切面切的是service层,当切换数据源时,一定要把所有的方法加到你要实施事务的attributes中,或者写成*(任何方法都实施事务)也可以.否则不能切换数据源,详情可见http://blog.csdn.net/wangpeng047/article/details/43450189的博客

这里一句话带过,事务和数据源是绑定的,当你在service层加上事务,你想在dao层切换数据源是不可以的,由于在进入该层之前事务已经通过拦截器开启,因此在该层切换数据源也是不行的.

以上是我本地配置的带事务管理的数据源切换实例,如有问题感谢大家提出指正互相学习.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息