springboot2.x+mybatis plus整合多數據源
一、springboot2.x+mybatis plus整合多數據源
1.1 數據庫
oa庫
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵id',
`username` varchar(50) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`password` varchar(500) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
`name` varchar(25) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '姓名',
`sex` char(1) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '1' COMMENT '0:女',
`status` char(1) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT '1' COMMENT '用戶的屬性 1-編制 2-兼職',
PRIMARY KEY (`id`) USING BTREE,
)
cdt庫
DROP TABLE IF EXISTS `cdt_user`;
CREATE TABLE `cdt_user` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶id',
`pwd` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
`nickName` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '暱稱',
`sex` int(1) DEFAULT 0 COMMENT '0代表女 1代表男',
`countryCode` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '86-中國 ; 0081 - 日本 ',
`mobile` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '電話號碼',
`headPic` text CHARACTER SET utf8 COLLATE utf8_general_ci COMMENT '頭像',
`age` int(11) DEFAULT 18 COMMENT '年齡',
)
1.2 生成映射文件
MybatisplusUtil.java映射文件生成工具生成映射文件
package com.hanergy.out.utils;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
/**
* 數據庫生成JAVA類
*/
public class MybatisPlusUtils {
public static String[] getAllTables() {
List<String> list = new ArrayList<>();
try {
Connection connection = DriverManager.getConnection("jdbc:mysql://rm-e.mysql.rds.aliyuncs.com:3306/cdt?useSSL=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull", "root", "xxxx");
DatabaseMetaData metaData = connection.getMetaData();
ResultSet tables = metaData.getTables(null, null, null, new String[]{"TABLE"});
while (tables.next()) {
list.add(tables.getString(3));
}
} catch (SQLException e) {
e.printStackTrace();
}
return list.toArray(new String[]{});
}
/**
* 自動代碼生成類
*
* @param includeTables
* @param excludeTables
*/
public static void generateMysql(String[] includeTables, String[] excludeTables, Boolean db1) {
AutoGenerator autoGenerator = new AutoGenerator();
/**
* 數據庫配置
*/
buildDb(autoGenerator);
/**
* 數據庫表配置
*/
StrategyConfig strategyConfig = new StrategyConfig();
// 駝峯命名
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
strategyConfig.setNaming(NamingStrategy.underline_to_camel);
// 需要生成的表名
// includeTables = new String[]{"user"};
// 不需要生成的表名
// excludeTables = new String[]{};
strategyConfig.setInclude(includeTables);
strategyConfig.setExclude(excludeTables);
strategyConfig.setTablePrefix("");
autoGenerator.setStrategy(strategyConfig);
/**
* 全局配置
*/
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setAuthor("Du Ronghong");
globalConfig.setDateType(DateType.ONLY_DATE);
globalConfig.setActiveRecord(true);
globalConfig.setIdType(IdType.INPUT);
globalConfig.setOutputDir("D:/test/video");
globalConfig.setMapperName("%sMapper");
globalConfig.setServiceName("I%sService");
globalConfig.setServiceImplName("%sServiceImpl");
globalConfig.setXmlName("%sMapper");
//globalConfig.setSwagger2(true);
globalConfig.setFileOverride(true);
globalConfig.setBaseColumnList(false);
globalConfig.setBaseResultMap(false);
globalConfig.setEnableCache(false);
autoGenerator.setGlobalConfig(globalConfig);
/**
* 包名配置
*/
PackageConfig packageConfig = new PackageConfig();
packageConfig.setParent("");
packageConfig.setEntity("com.hanergy.out.entity");
packageConfig.setMapper("com.hanergy.out.dao");
packageConfig.setXml("mapper");
packageConfig.setService("com.hanergy.out.service");
packageConfig.setServiceImpl("com.hanergy.out.service.impl");
packageConfig.setController("com.hanergy.out.controller");
autoGenerator.setPackageInfo(packageConfig);
// 採用默認模板,自定義模板參考@see com.baomidou.mybatisplus.generator.config.TemplateConfig
// TemplateConfig templateConfig = new TemplateConfig();
autoGenerator.setTemplateEngine(new FreemarkerTemplateEngine());
autoGenerator.execute();
}
private static void buildDb(AutoGenerator autoGenerator) {
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setDbType(DbType.MYSQL);
dataSourceConfig.setDriverName("com.mysql.jdbc.Driver");
dataSourceConfig.setUsername("root");
dataSourceConfig.setPassword("xxxx");
dataSourceConfig.setUrl("jdbc:mysql://rmo.mysql.rds.aliyuncs.com:3306/cdt?useSSL=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull");
autoGenerator.setDataSource(dataSourceConfig);
}
//com.hanergy.modules.activiti.entity
public static void main(String[] args) {
//要生成映射的表名
String[] includeTables = {"hr_kpi_dept_person","sys_user"};
generateMysql(includeTables,null,false);
}
}
1.3 項目結構
二、多數據源配置
2.1 pom.xml
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.0-gamma</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
<!--引入AOP依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.1.6.RELEASE</version>
</dependency>
2.2 填寫配置信息
application.yml配置mybatisplus以及多數據源
spring:
aop:
auto: true
proxy-target-class: true
datasource:
druid:
#oa
oa:
url: jdbc:mysql://rm-2zezdhr94r3t4et671o.mysql.rds.aliyuncs.com:3306/oa?useSSL=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
username: root
password: ArA8IyYFmQcrlxJP
driver-class-name: com.mysql.jdbc.Driver
initialSize: 5
minIdle: 5
maxActive: 20
#cdt
cdt:
url: jdbc:mysql://rm-2zezdhr94r3t4et671o.mysql.rds.aliyuncs.com:3306/cdt?useSSL=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
username: root
password: ArA8IyYFmQcrlxJP
driver-class-name: com.mysql.jdbc.Driver
initialSize: 5
minIdle: 5
maxActive: 20
#mybatis
mybatis-plus:
mapper-locations: classpath:mybatis/*.xml
#實體掃描,多個package用逗號或者分號分隔
typeAliasesPackage: com.hanergy.out.*.entity
global-config:
#自定義SQL注入器
db-config:
#主鍵類型 0:"數據庫ID自增", 1:"用戶輸入ID",2:"全局唯一ID (數字類型唯一ID)", 3:"全局唯一ID UUID";
id-type: input
#字段策略 0:"忽略判斷",1:"非 NULL 判斷"),2:"非空判斷"
field-strategy: NOT_NULL
#邏輯刪除配置
logic-delete-value: -1
logic-not-delete-value: 0
#刷新mapper 調試神器
refresh: true
2.3 數據源配置
package com.hanergy.out.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
//import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @author : hld
* @date : 2017/9/6
*/
@Configuration
public class DataSourceConfig {
/**
* 動態數據源配置
*
* @param dataSourceOrder : 訂單數據源
* @param dataSourceUser : 用戶數據源
* @return
*/
@Bean
public DynamicMultipleDataSource multipleDataSource ( @Qualifier( GlobalConstant.OA_DATA_SOURCE_KEY ) DataSource dataSourceOrder ,
@Qualifier( GlobalConstant.CDT_DATA_SOURCE_KEY ) DataSource dataSourceUser ) {
DynamicMultipleDataSource dynamicMultipleDataSource = new DynamicMultipleDataSource();
Map< Object, Object > targetDataSources = new HashMap<>();
targetDataSources.put( GlobalConstant.OA_DATA_SOURCE_KEY , dataSourceOrder );
targetDataSources.put( GlobalConstant.CDT_DATA_SOURCE_KEY , dataSourceUser );
dynamicMultipleDataSource.setTargetDataSources( targetDataSources );
dynamicMultipleDataSource.setDefaultTargetDataSource( dataSourceOrder );
return dynamicMultipleDataSource;
}
@Primary
@Bean
@ConfigurationProperties( prefix = "spring.datasource.druid.oa" )
public DataSource oa () {
return DruidDataSourceBuilder.create().build();
}
@Bean
@ConfigurationProperties( prefix = "spring.datasource.druid.cdt" )
public DataSource cdt () {
return DruidDataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory sqlSessionFactory (DynamicMultipleDataSource dynamicMultipleDataSource ) throws
Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource( dynamicMultipleDataSource );
return sqlSessionFactoryBean.getObject();
}
@Bean
public DataSourceTransactionManager transactionManager (DynamicMultipleDataSource dynamicMultipleDataSource ) throws
Exception {
return new DataSourceTransactionManager( dynamicMultipleDataSource );
}
@Bean
@Primary
public MybatisSqlSessionFactoryBean mybatisSqlSessionFactoryBean (DynamicMultipleDataSource dynamicMultipleDataSource ) {
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource( dynamicMultipleDataSource );
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
// 不加上這句話多數據源配置 mybatisplus正常 但是讀取.xml sql會報錯找不到方法。
sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/*.xml"));
return sqlSessionFactoryBean;
}
}
package com.hanergy.out.config;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 動態數據源註解
* {@link DataSourceSwitch}
*
* @author : hld
* @date : 2017/9/6
*/
@Retention( RetentionPolicy.RUNTIME )
@Target( { ElementType.METHOD , ElementType.TYPE } )
public @interface DynamicDataSource {
@AliasFor( "dataSource" )
String value() default StringUtils.EMPTY;
@AliasFor( "value" )
String dataSource() default StringUtils.EMPTY;
}
package com.hanergy.out.config;
/**
* 全局常量
*
* @author : hld
* @date : 2017/9/7
*/
public abstract class GlobalConstant {
/** 多數據源key : 訂單系統數據源 **/
public static final String OA_DATA_SOURCE_KEY = "oa";
/** 多數據源key : 用戶系統數據源 **/
public static final String CDT_DATA_SOURCE_KEY = "cdt";
}
package com.hanergy.out.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author : hld
* @date : 2017/5/10
* mybatis:xml文件路徑
*/
@Configuration
@MapperScan( {
"mybatis",
} )
public class MybatisPlusConfig {
/**
* 分頁插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
/**
* mybatis-plus 性能分析攔截器<br>
* 文檔:http://mp.baomidou.com<br>
*/
@Bean
public PerformanceInterceptor performanceInterceptor () {
return new PerformanceInterceptor();
}
}
package com.hanergy.out.config;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* @author : hld
*/
public class DataSourceSwitchMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke ( MethodInvocation invocation ) throws Throwable {
final String packageName = invocation.getThis().getClass().getPackage().getName();
if ( packageName.contains( "cdt" ) ) {
setDataSourceKey( invocation.getMethod() , GlobalConstant.CDT_DATA_SOURCE_KEY );
}
if ( packageName.contains( "oa" ) ) {
setDataSourceKey( invocation.getMethod() , GlobalConstant.OA_DATA_SOURCE_KEY );
}
return invocation.proceed();
}
/**
* 設置數據源key
*/
private void setDataSourceKey ( final Method method , final String defaultKey ) {
final DynamicDataSource dynamicDataSource = method.getAnnotation( DynamicDataSource.class );
if ( Objects.isNull( dynamicDataSource ) ) {
DynamicMultipleDataSource.setDataSourceKey( defaultKey );
return;
}
DynamicMultipleDataSource.setDataSourceKey( dynamicDataSource.value() );
}
}
2.4 利用AOP進行數據源的動態切換
package com.hanergy.out.config;
import com.hanergy.out.Interceptor.LoginInterceptor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* @author : hld
* @date : 2017/9/6
*/
@Aspect
@Order( -100 ) //數值越小 越優先執行
@Component
public class DataSourceSwitch {
Logger log = LoggerFactory.getLogger(DataSourceSwitch.class);
@Before( "execution(* com.hanergy.out.service.oa..*.*(..))" )
public void dataPlatform ( JoinPoint joinPoint ) {
log.info("切換數據源oa");
setDataSourceKey( joinPoint , GlobalConstant.OA_DATA_SOURCE_KEY );
}
@Before( "execution(* com.hanergy.out.service.cdt..*.*(..))" )
public void shop ( JoinPoint joinPoint ) {
log.info("切換數據源cdt");
setDataSourceKey( joinPoint , GlobalConstant.CDT_DATA_SOURCE_KEY );
}
/**
* 設置數據源key
*/
private void setDataSourceKey (JoinPoint joinPoint , final String defaultKey ) {
final Method method = this.currentMethod( joinPoint );
final DynamicDataSource dynamicDataSource = method.getAnnotation( DynamicDataSource.class );
if ( Objects.isNull( dynamicDataSource ) ) {
DynamicMultipleDataSource.setDataSourceKey( defaultKey );
return;
}
DynamicMultipleDataSource.setDataSourceKey( dynamicDataSource.value() );
}
/**
* 獲取當前執行的方法
*/
private Method currentMethod ( JoinPoint joinPoint ) {
return ( (MethodSignature) joinPoint.getSignature() ).getMethod();
}
}
package com.hanergy.out.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* 動態數據源路由
*
* @author : hld
* @date : 2017/9/6
*/
public class DynamicMultipleDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal< String > DATA_SOURCE_KEY = new ThreadLocal<>();
static void setDataSourceKey ( String dataSource ) {
DATA_SOURCE_KEY.set( dataSource );
}
private static void clear () {
DATA_SOURCE_KEY.remove();
}
@Override
protected Object determineCurrentLookupKey () {
final String lookupKey = DATA_SOURCE_KEY.get();
clear();
return lookupKey;
}
}
2.5 多數據源事務
package com.hanergy.out.config;
import org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RollbackRuleAttribute;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author : 披荊斬棘
* @date : 2017/9/8
*/
@Configuration
@ConfigurationProperties( prefix = "transactional" )
public class TransactionalConfig {
private static final String CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME = "customizeTransactionInterceptor";
private static final String DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME = "dataSourceSwitchMethodInterceptor";
/**
* 默認只對 "*Service" , "*ServiceImpl" Bean 進行事務處理,"*"表示模糊匹配, 比如 : userService,orderServiceImpl
*/
private static final String[] DEFAULT_TRANSACTION_BEAN_NAMES = { "*Service" , "*ServiceImpl" };
/**
* 可傳播事務配置
*/
private static final String[] DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES = {
"add*" ,
"save*" ,
"insert*" ,
"delete*" ,
"update*" ,
"edit*" ,
"batch*" ,
"create*" ,
"remove*" ,
};
/**
* 默認的只讀事務
*/
private static final String[] DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES = {
"get*" ,
"count*" ,
"find*" ,
"query*" ,
"select*" ,
"list*" ,
"*" ,
};
/**
* 自定義事務 BeanName 攔截
*/
private String[] customizeTransactionBeanNames = {};
/**
* 自定義方法名的事務屬性相關聯,可以使用通配符(*)字符關聯相同的事務屬性的設置方法; 只讀事務
*/
private String[] customizeReadOnlyMethodRuleTransactionAttributes = {};
/**
* 自定義方法名的事務屬性相關聯,可以使用通配符(*)字符關聯相同的事務屬性的設置方法;
* 傳播事務(默認的){@link org.springframework.transaction.annotation.Propagation#REQUIRED}
*/
private String[] customizeRequiredMethodRuleTransactionAttributes = {};
/**
* 配置事務攔截器
*
* @param transactionManager : 事務管理器
* @return
*/
@Bean( CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME )
public TransactionInterceptor customizeTransactionInterceptor (PlatformTransactionManager transactionManager ) {
NameMatchTransactionAttributeSource transactionAttributeSource = new NameMatchTransactionAttributeSource();
RuleBasedTransactionAttribute readOnly = this.readOnlyTransactionRule();
RuleBasedTransactionAttribute required = this.requiredTransactionRule();
// 默認的只讀事務配置
for ( String methodName : DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES ) {
transactionAttributeSource.addTransactionalMethod( methodName , readOnly );
}
// 默認的傳播事務配置
for ( String methodName : DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES ) {
transactionAttributeSource.addTransactionalMethod( methodName , required );
}
// 定製的只讀事務配置
for ( String methodName : customizeReadOnlyMethodRuleTransactionAttributes ) {
transactionAttributeSource.addTransactionalMethod( methodName , readOnly );
}
// 定製的傳播事務配置
for ( String methodName : customizeRequiredMethodRuleTransactionAttributes ) {
transactionAttributeSource.addTransactionalMethod( methodName , required );
}
return new TransactionInterceptor( transactionManager , transactionAttributeSource );
}
/**
* 配置事務 AOP 切入點
* {@link DataSourceSwitch}
*
* @param transactionInterceptor : {@link #customizeTransactionInterceptor(PlatformTransactionManager)}
@Bean public AspectJExpressionPointcutAdvisor aspectJExpressionPointcutAdvisor ( @Qualifier( "customizeTransactionInterceptor" ) TransactionInterceptor transactionInterceptor ) {
AspectJExpressionPointcutAdvisor pointcut = new AspectJExpressionPointcutAdvisor();
pointcut.setAdvice( transactionInterceptor );
pointcut.setExpression( "execution (* com.aidijing.*.*service.*.*(..))" );
return pointcut;
}
*/
/**
* {@link #dataSourceSwitchMethodInterceptor()}
* {@link #customizeTransactionInterceptor(PlatformTransactionManager)}
*
* @return
*/
@Bean
public BeanNameAutoProxyCreator beanNameAutoProxyCreator () {
BeanNameAutoProxyCreator beanNameAutoProxyCreator = new BeanNameAutoProxyCreator();
beanNameAutoProxyCreator.setInterceptorNames( DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME ,
CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME );
List< String > transactionBeanNames = new ArrayList<>( DEFAULT_TRANSACTION_BEAN_NAMES.length + customizeTransactionBeanNames.length );
// 默認
transactionBeanNames.addAll( Arrays.asList( DEFAULT_TRANSACTION_BEAN_NAMES ) );
// 定製
transactionBeanNames.addAll( Arrays.asList( customizeTransactionBeanNames ) );
// 歸集
for ( String transactionBeanName : transactionBeanNames ) {
beanNameAutoProxyCreator.setBeanNames( transactionBeanName );
}
beanNameAutoProxyCreator.setProxyTargetClass( true );
return beanNameAutoProxyCreator;
}
@Bean( DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME )
public DataSourceSwitchMethodInterceptor dataSourceSwitchMethodInterceptor () {
return new DataSourceSwitchMethodInterceptor();
}
/**
* 支持當前事務;如果不存在創建一個新的
*/
private RuleBasedTransactionAttribute requiredTransactionRule () {
RuleBasedTransactionAttribute required = new RuleBasedTransactionAttribute();
required.setRollbackRules( Collections.singletonList( new RollbackRuleAttribute( Exception.class ) ) );
required.setPropagationBehavior( TransactionDefinition.PROPAGATION_REQUIRED );
required.setTimeout( TransactionDefinition.TIMEOUT_DEFAULT );
return required;
}
/**
* 只讀事務
*/
private RuleBasedTransactionAttribute readOnlyTransactionRule () {
RuleBasedTransactionAttribute readOnly = new RuleBasedTransactionAttribute();
readOnly.setReadOnly( true );
readOnly.setPropagationBehavior( TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
return readOnly;
}
public static String getCustomizeTransactionInterceptorName() {
return CUSTOMIZE_TRANSACTION_INTERCEPTOR_NAME;
}
public static String getDataSourceSwitchMethodInterceptorName() {
return DATA_SOURCE_SWITCH_METHOD_INTERCEPTOR_NAME;
}
public static String[] getDefaultTransactionBeanNames() {
return DEFAULT_TRANSACTION_BEAN_NAMES;
}
public static String[] getDefaultRequiredMethodRuleTransactionAttributes() {
return DEFAULT_REQUIRED_METHOD_RULE_TRANSACTION_ATTRIBUTES;
}
public static String[] getDefaultReadOnlyMethodRuleTransactionAttributes() {
return DEFAULT_READ_ONLY_METHOD_RULE_TRANSACTION_ATTRIBUTES;
}
public String[] getCustomizeTransactionBeanNames() {
return customizeTransactionBeanNames;
}
public void setCustomizeTransactionBeanNames(String[] customizeTransactionBeanNames) {
this.customizeTransactionBeanNames = customizeTransactionBeanNames;
}
public String[] getCustomizeReadOnlyMethodRuleTransactionAttributes() {
return customizeReadOnlyMethodRuleTransactionAttributes;
}
public void setCustomizeReadOnlyMethodRuleTransactionAttributes(String[] customizeReadOnlyMethodRuleTransactionAttributes) {
this.customizeReadOnlyMethodRuleTransactionAttributes = customizeReadOnlyMethodRuleTransactionAttributes;
}
public String[] getCustomizeRequiredMethodRuleTransactionAttributes() {
return customizeRequiredMethodRuleTransactionAttributes;
}
public void setCustomizeRequiredMethodRuleTransactionAttributes(String[] customizeRequiredMethodRuleTransactionAttributes) {
this.customizeRequiredMethodRuleTransactionAttributes = customizeRequiredMethodRuleTransactionAttributes;
}
}
三、測試
controller添加@Transactional事務註解
@ApiOperation(value="根據訂單號獲取訂單信息",notes="根據訂單號獲取訂單信息")
@ApiImplicitParams({
@ApiImplicitParam(name="historyId",value="訂單號",required=true,paramType="query")
})
@GetMapping("/order")
public R findHistoryInfo(@RequestParam("historyId")Integer historyId) {
log.info(historyId.toString());
//cdt庫查詢數據
CdtCheckHistory cdtCheckHistory = cdtCheckHistoryService.findByHistoryId(historyId);
SysUser sysUser = new SysUser();
sysUser.setEmail("11111");
sysUser.setName("111111");
sysUser.setUsername("111111");
sysUser.setImage("111111");
// oa庫
sysUserService.insert(sysUser);
// cdt庫
CdtCheckHistory cdtCheckHistory1 = cdtCheckHistoryService.findByHistoryId(historyId);
// 事務測試
int i = 1/0;
return R.ok(200,cdtCheckHistory);
}