SpringMVC+Mybatis 多数据源配置
来源:互联网 发布:水泥凝结时间测定数据 编辑:程序博客网 时间:2024/06/05 00:09
浪费了一上午的时间,参考了各种大神的帖子,并不好用。有的是能用,但不支持事务,有的压根因为配置习惯的不同或者spring版本不一样,配置也不能用,这里粘贴下我自己的配置,希望能帮你找到一些思路,如果能直接集成成功,那是最好啦
废话不多说,直接上代码。
1、项目为Spring-SpringMVC-Mybatis maven
2、SpringMVC 版本 4.3
3、开发工具 IDEA
4、数据库连接池用的阿里 druid
主要修改以下配置:
- jdbc.properties
- springMvcContext-base.xml
- 增加相关代码块
1、修改jdbc.properties
driver=com.microsoft.sqlserver.jdbc.SQLServerDriverurl=jdbc:sqlserver://192.168.0.188:1433;databaseName=xxxxxxxusername=sapassword=savalidationQuery:select 1driver_two=oracle.jdbc.driver.OracleDriverurl_two=jdbc:oracle:thin:@192.168.0.188:1521:ORCLusername_two=sapassword_two=savalidationQuery_two:select 1 from dualfilters:statmaxActive:20initialSize:1maxWait:60000minIdle:10maxIdle:15timeBetweenEvictionRunsMillis:60000minEvictableIdleTimeMillis:300000testWhileIdle:truetestOnBorrow:falsetestOnReturn:falsemaxOpenPreparedStatements:20removeAbandoned:trueremoveAbandonedTimeout:1800logAbandoned:true
2、修改springMvcContext-base.xml
(只有核心配置,其他的不贴了)
<!-- 配置数据源_2:阿里 druid数据库连接池 --> <bean id="dataSource_sqlserver" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <!-- 数据库基本信息配置 --> <property name="url" value="${url}" /> <property name="username" value="${username}" /> <property name="password" value="${password}" /> <property name="driverClassName" value="${driver}" /> <property name="filters" value="${filters}" /> <!-- 最大并发连接数 --> <property name="maxActive" value="${maxActive}" /> <!-- 初始化连接数量 --> <property name="initialSize" value="${initialSize}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="${maxWait}" /> <!-- 最小空闲连接数 --> <property name="minIdle" value="${minIdle}" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${validationQuery}" /> <property name="testWhileIdle" value="${testWhileIdle}" /> <property name="testOnBorrow" value="${testOnBorrow}" /> <property name="testOnReturn" value="${testOnReturn}" /> <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 1800秒,也就是30分钟 --> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="${logAbandoned}" /> </bean> <bean id="dataSource_oracle" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <!-- 数据库基本信息配置 --> <property name="url" value="${url_two}" /> <property name="username" value="${username_two}" /> <property name="password" value="${password_two}" /> <property name="driverClassName" value="${driver_two}" /> <property name="filters" value="${filters}" /> <!-- 最大并发连接数 --> <property name="maxActive" value="${maxActive}" /> <!-- 初始化连接数量 --> <property name="initialSize" value="${initialSize}" /> <!-- 配置获取连接等待超时的时间 --> <property name="maxWait" value="${maxWait}" /> <!-- 最小空闲连接数 --> <property name="minIdle" value="${minIdle}" /> <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" /> <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 --> <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" /> <property name="validationQuery" value="${validationQuery_two}" /> <property name="testWhileIdle" value="${testWhileIdle}" /> <property name="testOnBorrow" value="${testOnBorrow}" /> <property name="testOnReturn" value="${testOnReturn}" /> <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" /> <!-- 打开removeAbandoned功能 --> <property name="removeAbandoned" value="${removeAbandoned}" /> <!-- 1800秒,也就是30分钟 --> <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" /> <!-- 关闭abanded连接时输出错误日志 --> <property name="logAbandoned" value="${logAbandoned}" /> </bean>关键在此---------- <!--双数据源--> <bean id="dataSource" class="com.googosoft.util.double_datasource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSource_sqlserver" key="dataSource_sqlserver"></entry><!--数据源的名字--> <entry value-ref="dataSource_oracle" key="dataSource_oracle"></entry> </map><!--数据源的名字--> </property> </bean> <!-- 配置数据库注解aop --> <bean id="dataSourceAspect" class="com.alibaba.util.double_datasource.DataSourceAspect"/> <!-- 使用aop技术实现事物处理 --> <aop:config> <!-- id:事务切入点名称 expression:事务切入点正则表达式 --> <aop:pointcut id="serviceMethods" expression="execution(* com.alibaba.serviceImpl..*.*(..))" /><!-- expression="execution(* com.alibaba.serviceImpl.*.*(..))" /> --> <!-- pointcut-ref:事务切入点名称 advice-ref:事务通知名称 --> <!--数据源选择切面,保证在事务开始之前执行--> <aop:advisor pointcut-ref="serviceMethods" advice-ref="dataSourceAspect" order="1" /><!--数据源切面执行顺序--> <aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" order="2" /><!--数据源的名字--> </aop:config>---------- <!-- 配置Session工厂 --> <!-- spring和MyBatis整合--> <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <!-- 指明mybatis主配置文件路径 --> <property name="configLocation" value="classpath:mybatis.cfg.xml"></property> <!-- 指明mybatis的映射位置 自动扫描需要定义类别名的包,将包内的JAVA类的类名作为类别名--> <property name="mapperLocations"> <list> <value>classpath:orm/**/*.xml</value> </list> </property> </bean><!-- DAO接口所在包名,Spring会自动查找其下的类 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.alibaba.mapper" /> <property name="sqlSessionFactoryBeanName" value="sessionFactory"></property> </bean> <!-- 配置SqlSession模版类--> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype"> <constructor-arg ref="sessionFactory"></constructor-arg> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"></property> </bean> <!-- 配置事务通知 id:事务通知名称,transaction-manager:指定事务管理器名称 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 以delete、insert、update、sava、do、go开头的所有方法采用只读型事务控制类型 --> <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" /> <tx:method name="do*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" timeout="10" /> <tx:method name="go*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" timeout="10" /> <!-- 以load、find、search、select、get开头的所有方法采用只读型事务控制类型 --> <tx:method name="load*" propagation="SUPPORTS" read-only="true"/> <tx:method name="find*" propagation="SUPPORTS" read-only="true"/> <tx:method name="search*" propagation="SUPPORTS" read-only="true"/> <tx:method name="select*" propagation="SUPPORTS" read-only="true"/> <tx:method name="get*" propagation="SUPPORTS" read-only="true"/> <tx:method name="*" propagation="SUPPORTS" read-only="true"/> </tx:attributes> </tx:advice>
3、增加相关代码块
注:利用注解实现动态切换相关数据源
DynamicDataSource.class
/** * 类名:DynamicDataSource.class * 描述:动态数据源类 * -------------------------------------- * 修改内容: * 备注: * Modify by: */public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { String dataSource =DynamicDataSourceHolder.getDataSourceType(); return dataSource; }}
DynamicDataSourceHolder.class
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * 类名:DynamicDataSourceHolder.class * 描述:获得和设置上下文环境的类,主要负责改变上下文数据源的名称 * -------------------------------------- * 修改内容: * 备注: * Modify by: */public class DynamicDataSourceHolder { private static final ThreadLocal<String> contextHolder= new ThreadLocal<String>(); public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDataSourceType() { return contextHolder.get(); } public static void clearDataSourceType() { contextHolder.remove(); }}
DataSourceAspect.class
import org.springframework.aop.AfterReturningAdvice;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;/** * 类名:DataSourceAspect.class * 描述:数据源切面支持,在开启事务之前选择默认的数据源 * -------------------------------------- * 修改内容: * 备注: * Modify by: */public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice{ public static final String dataSource_sqlserver = "dataSource_sqlserver"; public static final String dataSource_oracle = "dataSource_oracle"; @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { DynamicDataSourceHolder.clearDataSourceType(); } @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); DynamicDataSourceHolder.setDataSourceType(datasource.name()); //方法上的数据源 优先级高于类上的 } else if (method.isAnnotationPresent(DataSource.class)) { DataSource datasource = method.getAnnotation(DataSource.class); DynamicDataSourceHolder.setDataSourceType(datasource.name()); } else { DynamicDataSourceHolder.setDataSourceType(dataSource_sqlserver); } }}
DataSource.class
import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.Target;import static java.lang.annotation.RetentionPolicy.RUNTIME;/** * 类名:DataSource.class * 描述:数据源切换注解 * -------------------------------------- * 修改内容: * 备注: * Modify by: */@Documented@Retention(RUNTIME)@Target({ElementType.METHOD,ElementType.TYPE})public @interface DataSource { String name();// String name() default DataSource.dataSource_sqlserver;}
调用方法
在如果你的事务控制在service层,建议在controller下调用 添加如下代码块(支持在类和方法级调用)
@DataSource(name = DataSourceAspect.dataSource_oracle)
关于一些疑问:
动态切换数据源以后,需要再切换回来吗?答案:不需要,因为之前已经设置默认的数据源,只有添加注解DataSource的地方,才能改变数据源,如果其他类或者方法没有添加此注解DataSource,将用默认数据源执行数据库操作。
所以,建议在项目初始就将访问不同数据源的controller 或者业务进行分包管理,防止代码混乱
- springmvc mybatis多数据源配置
- SpringMvc+Mybatis多数据源配置
- springMvc+mybatis多数据源配置
- spring+springMVC+mybatis 多数据源配置
- springmvc + mybatis多数据源配置
- springmvc+mybatis多数据源配置
- SpringMVC+ Mybatis 配置多数据源切换
- SpringMVC + Mybatis 配置多数据源
- SpringMVC+Mybatis 多数据源配置
- springMVC+myBatis多数据源
- springmvc+mybatis 配置多数据源相互切换
- springMVC+mybatis多数据源配置(dao扫描版本)
- springMvc-Mybatis 实现主从数据库/多数据源切换配置
- mybatis + springMVC 多数据源,及事务配置
- 【Java】一次SpringMVC+ Mybatis 配置多数据源经历
- 【Java】一次SpringMVC+ Mybatis 配置多数据源经历
- 关于spring+springMvc+mybatis整合,配置多数据源
- springmvc 多数据源配置
- HashMap工作原理
- mysql集群技术:主从复制,读写分离
- h5标题和列表的学习
- 【转】Centos7.3防火墙配置
- go语言基础
- SpringMVC+Mybatis 多数据源配置
- 使用 pprof 和火焰图调试 golang 应用
- linux信号
- 剑指offer之求1+2+3+4+。。。+n
- RxJava-Subject
- python 文件、文件夹和路径操作笔记
- RN工程添加第三方库
- System Power Management Sleep States
- Linux 常用操作