本文环境接上文多数据源配置的环境。
如果采用不同的数据源,当同时对不同的数据源进行操作时,事务无法正确的回滚,此时需要使用MysqlXADataSource来代理数据源。
MybatisDBD1Config.java:
package com.bxw.configuration;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
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.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* 分布式事务管理
*/
@Configuration
@MapperScan(basePackages = "com.bxw.mapperTA", sqlSessionTemplateRef = "sqlSessionTemplateT1")
public class MybatisDBD1Config {
@Primary
@Bean(name = "datasourceT1")
public DataSource dataSource(DBConfig1 dbConfig1)throws SQLException{
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(dbConfig1.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(dbConfig1.getPassword());
mysqlXaDataSource.setUser(dbConfig1.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("dbb1");
// xaDataSource.setMinPoolSize(dbConfig1.getMinPoolSize());
// xaDataSource.setMaxPoolSize(dbConfig1.getMaxPoolSize());
// xaDataSource.setMaxLifetime(dbConfig1.getMaxLifetime());
// xaDataSource.setBorrowConnectionTimeout(dbConfig1.getBorrowConnectionTimeout());
// xaDataSource.setLoginTimeout(dbConfig1.getLoginTimeout());
// xaDataSource.setMaintenanceInterval(dbConfig1.getMaintenanceInterval());
// xaDataSource.setMaxIdleTime(dbConfig1.getMaxIdleTime());
// xaDataSource.setTestQuery(dbConfig1.getTestQuery());
return xaDataSource;
}
@Bean(name = "sqlSessionFactoryT1")
public SqlSessionFactory sqlSessionFactory(@Qualifier("datasourceT1") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource); // 使用db1数据源, 连接hibernate库
return factoryBean.getObject();
}
@Bean(name="sqlSessionTemplateT1")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryT1") SqlSessionFactory sqlSessionFactory) throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory); // 使用上面配置的Factory
return template;
}
}
MybatisDBD2Config.java:
package com.bxw.configuration;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource;
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.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
/**
* 分布式事务管理
*/
@Configuration
@MapperScan(basePackages = "com.bxw.mapperTB", sqlSessionTemplateRef = "sqlSessionTemplateT2")
public class MybatisDBD2Config {
@Bean(name = "datasourceT2")
public DataSource dataSource(DBConfig2 dbConfig2)throws SQLException{
MysqlXADataSource mysqlXaDataSource = new MysqlXADataSource();
mysqlXaDataSource.setUrl(dbConfig2.getUrl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(dbConfig2.getPassword());
mysqlXaDataSource.setUser(dbConfig2.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("dbb2");
// xaDataSource.setMinPoolSize(dbConfig1.getMinPoolSize());
// xaDataSource.setMaxPoolSize(dbConfig1.getMaxPoolSize());
// xaDataSource.setMaxLifetime(dbConfig1.getMaxLifetime());
// xaDataSource.setBorrowConnectionTimeout(dbConfig1.getBorrowConnectionTimeout());
// xaDataSource.setLoginTimeout(dbConfig1.getLoginTimeout());
// xaDataSource.setMaintenanceInterval(dbConfig1.getMaintenanceInterval());
// xaDataSource.setMaxIdleTime(dbConfig1.getMaxIdleTime());
// xaDataSource.setTestQuery(dbConfig1.getTestQuery());
return xaDataSource;
}
@Bean(name = "sqlSessionFactoryT2")
public SqlSessionFactory sqlSessionFactory(@Qualifier("datasourceT2") DataSource dataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dataSource); // 使用db1数据源, 连接hibernate库
return factoryBean.getObject();
}
@Bean(name="sqlSessionTemplateT2")
public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactoryT2") SqlSessionFactory sqlSessionFactory) throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory); // 使用上面配置的Factory
return template;
}
}
创建sqlSessionFactory,SqlSessionTemplate
StudentService.java:
package com.bxw.service;
import com.bxw.annotation.DB;
import com.bxw.entity.Student;
import com.bxw.mapperTA.StudentMapperTA;
import com.bxw.mapperTB.StudentMapperTB;
import com.bxw.mapperDynamic.StudentMapperC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Service
public class StudentService {
@Autowired
private StudentMapperTA studentMapperTA;
@Autowired
private StudentMapperTB studentMapperTB;/*
分布式事务
*/
@Transactional
public boolean saveStudent(Student s){
studentMapperTA.addStudent(s);
studentMapperTB.addStudent(s);
int i = 1/0;
return true;
}
}