当前位置: 移动技术网 > IT编程>开发语言>Java > 解决spring mvc 多数据源切换,不支持事务控制的问题

解决spring mvc 多数据源切换,不支持事务控制的问题

2019年07月19日  | 移动技术网IT编程  | 我要评论

一个项目中需要使用两个数据库,oracle 和mysql,于是参考各个blog,实现此功能。写好后才发现,原来的事务失效了,我去...

spring-mybatis.xml 配置

<bean id="configreader" class="org.springframework.beans.factory.config.preferencesplaceholderconfigurer">
  <property name="locations">
   <list>
    <value>classpath:spring/db.properties</value>
   </list>
  </property>
  <property name="ignoreresourcenotfound" value="true"/>
 </bean>

 <bean id="datasource" class="com.mchange.v2.c3p0.combopooleddatasource">
  <property name="driverclass" value="${jdbc.oracle.driverclassname}"></property>
  <property name="jdbcurl" value="${jdbc.oracle.url}"></property>
  <property name="user" value="${jdbc.oracle.username}"></property>
  <property name="password" value="${jdbc.oracle.userpassword}"></property>

  <property name="acquireincrement" value="5"></property>
  <property name="initialpoolsize" value="5"></property>
  <property name="maxidletime" value="60"></property>
  <property name="maxpoolsize" value="100"></property>
  <property name="minpoolsize" value="5"></property>
 </bean>


 <!-- 配置数据源:mysql start -->
 <bean name="mysqldatasource" class="com.alibaba.druid.pool.druiddatasource"
   init-method="init" destroy-method="close">
  <property name="driverclassname" value="${jdbc.mysql.driverclassname}"/>
  <property name="url" value="${jdbc.mysql.url}"/>
  <property name="username" value="${jdbc.mysql.username}"/>
  <property name="password" value="${jdbc.mysql.userpassword}"/>

  <!-- 初始化连接大小 -->
  <property name="initialsize" value="5"/>
  <!-- 连接池最大使用连接数量 -->
  <property name="maxactive" value="30"/>
  <!-- 连接池最小空闲 -->
  <property name="minidle" value="2"/>
  <!-- 获取连接最大等待时间 -->
  <property name="maxwait" value="300"/>

  <property name="validationquery" value="select 1"/>
  <property name="testonborrow" value="false"/>
  <property name="testonreturn" value="false"/>
  <property name="testwhileidle" value="true"/>

  <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
  <property name="timebetweenevictionrunsmillis" value="10000"/>
  <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
  <property name="minevictableidletimemillis" value="30000"/>

  <!-- 打开removeabandoned功能 -->
  <property name="removeabandoned" value="true"/>
  <!-- 1800秒,也就是30分钟 -->
  <property name="removeabandonedtimeout" value="1800"/>
  <!-- 关闭abanded连接时输出错误日志 -->
  <property name="logabandoned" value="true"/>

  <!-- 监控数据库 -->
  <property name="filters" value="stat"/>
 </bean>


 <bean id="multipledatasource" class="com.we.database.multipledatasource">
  <property name="defaulttargetdatasource" ref="datasource"/>
  <property name="targetdatasources">
   <map>
    <entry key="oracledatasource" value-ref="datasource"/>
    <entry key="mysqldatasource" value-ref="mysqldatasource"/>
   </map>
  </property>
 </bean>

 <!-- oracle mybatis file -->
 <bean id="sqlsessionfactory" class="org.mybatis.spring.sqlsessionfactorybean">
  <property name="datasource" ref="multipledatasource"/>
  <!--<property name="configlocation" value="classpath:configuration.xml" /> -->
  <property name="mapperlocations" value="classpath:com/we/dao/mapper/*.xml"/>
 </bean>

 <bean class="org.mybatis.spring.mapper.mapperscannerconfigurer">
  <property name="basepackage" value="com.we.dao"/>
  <property name="sqlsessionfactorybeanname" value="sqlsessionfactory"/>
 </bean>


 <!-- configure transaction -->
 <bean id="transactionmanager"
   class="org.springframework.jdbc.datasource.datasourcetransactionmanager">
  <property name="datasource" ref="datasource"/>
 </bean>

 <!-- annotation transaction -->
 <tx:annotation-driven transaction-manager="transactionmanager" proxy-target-class="true"/>


 <!-- interception transatcion -->
 <tx:advice id="transactionadvice" transaction-manager="transactionmanager">
  <tx:attributes>
   <tx:method name="add*" propagation="required"/>
  </tx:attributes>
 </tx:advice>

 <!-- 配置数据库注解aop -->
 <bean id="datasourceaspect" class="com.we.database.datasourceaspect"/>

 <aop:config>
  <aop:pointcut id="transactionpointcut" expression="execution(* com.wewe.licai.service..*impl.*(..))"/>
  <aop:advisor pointcut-ref="transactionpointcut" advice-ref="transactionadvice" order="2"/>

  <!--数据源选择切面,保证在事务开始之前执行-->
  <aop:advisor pointcut-ref="transactionpointcut" advice-ref="datasourceaspect" order="1" />
 </aop:config>

注解切换,默认使用oracle数据源

@documented
@retention(retentionpolicy.runtime)
@target({elementtype.method,elementtype.type})

public @interface datasource {
  string name() default datasource.oracledatasource;
  string mysqldatasource = "mysqldatasource";
  string oracledatasource = "oracledatasource";
}

注解方式实现切换数据源,搜索注释,更换注释上面的数据源,支持类注释和方法注释

/**
 * created by eastday on 2017/9/21.
 */
public class datasourceaspect implements methodbeforeadvice,afterreturningadvice
{

 @override
 public void afterreturning(object returnvalue, method method,
        object[] args, object target) throws throwable {

  multipledatasource.cleardatasource();
 }

 @override
 public void before(method method, object[] args, object target)
   throws throwable {

  //首先取类上的数据源
  if(method.getdeclaringclass().isannotationpresent(datasource.class) && !method.isannotationpresent(datasource.class)) {

   datasource datasource = method.getdeclaringclass().getannotation(datasource.class);
   multipledatasource.setdatasource(datasource.name());

   //方法上的数据源 优先级高于类上的
  } else if (method.isannotationpresent(datasource.class)) {

   datasource datasource = method.getannotation(datasource.class);
   multipledatasource.setdatasource(datasource.name());
  }
  else
  {
   multipledatasource.setdatasource(datasource.oracledatasource);
  }
 }
}

继承abstractroutingdatasource实现数据源切换

public class multipledatasource extends abstractroutingdatasource {
 private static final threadlocal<string> datasources = new inheritablethreadlocal<string>();

 public static void setdatasource(string datasource) {
  datasources.set(datasource);
 }

 //清除数据源
 public static void cleardatasource() {
  datasources.remove();
 }

 @override
 protected object determinecurrentlookupkey() {
  return datasources.get();
 }
}

使用demo

@datasource(name = datasource.mysqldatasource)
public class contentserviceimpl implements icontentservice {

 @autowired
 private icontentdao contentdao;

 @override
 public content queryone(string type) {
  return contentdao.queryone(type);
 }
}

以上这篇解决spring mvc 多数据源切换,不支持事务控制的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持移动技术网。

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网