import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
/**
* 数据源1
*/
@Configuration
@MapperScan(basePackages = "com.example.mybatis.mapper",sqlSessionFactoryRef = "sqlSessionFactoryOne")
public class DataSourceConfigOne {
@Bean(name = "dataSourceOne")
@Primary// 表示这个数据源是默认数据源
// 读取application.properties中的配置参数映射成为一个对象,prefix表示参数的前缀
@ConfigurationProperties(prefix = "spring.datasource.one")
public DataSource dataSourceOne() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactoryOne")
@Primary
public SqlSessionFactory sqlSessionFactoryOne(@Qualifier("dataSourceOne") DataSource datasource)throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setMapperLocations(
// 设置mybatis的xml所在位置
new PathMatchingResourcePatternResolver().getResources("classpath:mapper/*.xml"));
bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
return bean.getObject();
}
@Bean(name = "transactionManagerOne")
public PlatformTransactionManager transactionManagerOne(@Qualifier("dataSourceOne") DataSource dataSourceOne) {
return new DataSourceTransactionManager(dataSourceOne);
}
@Primary
public SqlSessionTemplate sqlsessiontemplateOne(@Qualifier("sqlsessiontemplateOne") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
}
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import javax.sql.DataSource;
/**
* 数据源2
*/
@Configuration
@MapperScan(basePackages = "com.example.mybatis.mapper2",sqlSessionFactoryRef = "sqlSessionFactoryTwo")
public class DataSourceConfigTwo {
@Bean(name = "dataSourceTwo")
// 读取application.properties中的配置参数映射成为一个对象,prefix表示参数的前缀
@ConfigurationProperties(prefix = "spring.datasource.two")
public DataSource dataSourceTwo() {
return DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactoryTwo")
public SqlSessionFactory sqlSessionFactoryTwo(@Qualifier("dataSourceTwo") DataSource datasource)throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(datasource);
bean.setMapperLocations(
// 设置mybatis的xml所在位置
new PathMatchingResourcePatternResolver().getResources("classpath:mapper2/*.xml"));
bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);//下划线-驼峰映射
return bean.getObject();
}
@Bean(name = "transactionManagerTwo")
public PlatformTransactionManager transactionManagerTwo(@Qualifier("dataSourceTwo") DataSource dataSourceTwo) {
return new DataSourceTransactionManager(dataSourceTwo);
}
public SqlSessionTemplate sqlsessiontemplateTwo(@Qualifier("sqlsessiontemplateTwo") SqlSessionFactory sessionfactory) {
return new SqlSessionTemplate(sessionfactory);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.PARAMETER})
public @interface MoreTransaction {
String[] value() default {};
}
@Aspect
@Component
public class TransactionAop {
@Pointcut("@annotation(com.example.mybatis.config.aop.annotation.MoreTransaction)")
public void MoreTransaction() {
}
@Pointcut("execution(* com.example.mybatis.controller.*.*(..))")
public void excudeController() {
}
@Around(value = "MoreTransaction()&&excudeController()&&@annotation(annotation)")
public Object twiceAsOld(ProceedingJoinPoint thisJoinPoint, MoreTransaction annotation) throws Throwable {
Stack
Stack
try {
if (!openTransaction(dataSourceTransactionManagerStack, transactionStatuStack, annotation)) {
return null;
}
Object ret = thisJoinPoint.proceed();
commit(dataSourceTransactionManagerStack, transactionStatuStack);
return ret;
} catch (Throwable e) {
rollback(dataSourceTransactionManagerStack, transactionStatuStack);
log.error(String.format("MultiTransactionalAspect, method:%s-%s occors error:",
thisJoinPoint.getTarget().getClass().getSimpleName(), thisJoinPoint.getSignature().getName()), e);
throw e;
}
}
/**
* 开启事务处理方法
*
* @param dataSourceTransactionManagerStack
* @param transactionStatuStack
* @param multiTransactional
* @return
*/
private boolean openTransaction(Stack
Stack
String[] transactionMangerNames = multiTransactional.value();
if (ArrayUtils.isEmpty(multiTransactional.value())) {
return false;
}
for (String beanName : transactionMangerNames) {
DataSourceTransactionManager dataSourceTransactionManager =(DataSourceTransactionManager) SpringContextUtil.getBean(beanName);
TransactionStatus transactionStatus = dataSourceTransactionManager
.getTransaction(new DefaultTransactionDefinition());
transactionStatuStack.push(transactionStatus);
dataSourceTransactionManagerStack.push(dataSourceTransactionManager);
}
return true;
}
/**
* 提交处理方法
*
* @param dataSourceTransactionManagerStack
* @param transactionStatuStack
*/
private void commit(Stack
Stack
while (!dataSourceTransactionManagerStack.isEmpty()) {
dataSourceTransactionManagerStack.pop().commit(transactionStatuStack.pop());
}
}
/**
* 回滚处理方法
* @param dataSourceTransactionManagerStack
* @param transactionStatuStack
*/
private void rollback(Stack
Stack
while (!dataSourceTransactionManagerStack.isEmpty()) {
dataSourceTransactionManagerStack.pop().rollback(transactionStatuStack.pop());
}
}
}
@Override
public int addUserInfo(UserInfo record) {
return userInfoMapper.insert(new UserInfo().setId(UUID.randomUUID().toString()).setUserAccount("吾问无为谓"));
}
@Override
public int addUser(User record) {
return userMapper.insertSelective(record);
}
@GetMapping("/dataSourceList")
@ResponseBody
@MoreTransaction(value = {"transactionManagerOne","transactionManagerTwo"})
public ResultData getDataSourceList(){
int i=userService.addUser(new User().setPhone("11111111111").setUserName("哈哈哈"));
int a=1/0;
int k=userService.addUserInfo(new UserInfo().setId(UUID.randomUUID().toString()).setUserAccount("吾问无为谓"));
Map map=new HashMap();
map.put("k",k);
return ResultData.success(map);
}