版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
在實際開發中,我們一個項目可能會用到多個數據庫,通常一個數據庫對應一個數據源。這時候就要管理多數據源事務。
什么是jta:https://www.ibm.com/developerworks/cn/java/j-lo-jta/
pom.xml
注意這里的druid用1.1.9
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-web
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-test
</artifactId>
-
<scope>test
</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.mybatis.spring.boot
</groupId>
-
<artifactId>mybatis-spring-boot-starter
</artifactId>
-
<version>1.1.1
</version>
-
</dependency>
-
<dependency>
-
<groupId>mysql
</groupId>
-
<artifactId>mysql-connector-java
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>com.alibaba
</groupId>
-
<artifactId>druid
</artifactId>
-
<version>1.1.9
</version>
-
</dependency>
-
<!-- JPA -->
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-data-jpa
</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot
</groupId>
-
<artifactId>spring-boot-starter-jta-atomikos
</artifactId>
-
</dependency>
配置第一個數據源
-
import com.alibaba.druid.pool.xa.DruidXADataSource;
-
import com.atomikos.icatch.jta.UserTransactionImp;
-
import com.atomikos.icatch.jta.UserTransactionManager;
-
import org.apache.ibatis.session.SqlSessionFactory;
-
import org.mybatis.spring.SqlSessionFactoryBean;
-
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 org.springframework.transaction.jta.JtaTransactionManager;
-
import javax.sql.DataSource;
-
import javax.transaction.UserTransaction;
-
-
-
@Configuration
-
// // 掃描 Mapper 接口並容器管理
-
@MapperScan(value ="mapper所在包路徑" ,sqlSessionFactoryRef = "moviesSqlSessionFactory")
-
public
class MoviesDataSourceConfig {
-
-
-
@Bean(name = "moviesDataSource")
-
@Primary
-
public DataSource masterDataSource() {
-
DruidXADataSource druidXADataSource = new DruidXADataSource();
-
druidXADataSource.setUrl(
"jdbc:mysql://localhost:3306/movies?useUnicode=true&characterEncoding=UTF8&useSSL=false");
-
druidXADataSource.setUsername(
"root");
-
druidXADataSource.setPassword(
"");
-
-
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
-
atomikosDataSourceBean.setXaDataSource(druidXADataSource);
-
atomikosDataSourceBean.setUniqueResourceName(
"moviesDataSource");
-
atomikosDataSourceBean.setPoolSize(
5);
-
-
return atomikosDataSourceBean;
-
}
-
-
/*
-
* 使用這個來做總事務 后面的數據源就不用設置事務了
-
* */
-
@Bean(name = "transactionManager")
-
@Primary
-
public JtaTransactionManager regTransactionManager () {
-
UserTransactionManager userTransactionManager = new UserTransactionManager();
-
UserTransaction userTransaction = new UserTransactionImp();
-
return new JtaTransactionManager(userTransaction, userTransactionManager);
-
}
-
-
@Bean(name = "moviesSqlSessionFactory")
-
@Primary
-
public SqlSessionFactory masterSqlSessionFactory(
@Qualifier("moviesDataSource") DataSource masterDataSource)
-
throws Exception {
-
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
-
sessionFactory.setDataSource(masterDataSource);
-
return sessionFactory.getObject();
-
}
-
-
-
-
}
注意:不管有多少個數據源只要配置一個 JtaTransactionManager。
還有 DataSource里用的是DruidXADataSource ,而后注冊到AtomikosDataSourceBean並且返回。
配置第二個數據源
-
import com.alibaba.druid.pool.xa.DruidXADataSource;
-
-
import org.apache.ibatis.session.SqlSessionFactory;
-
import org.mybatis.spring.SqlSessionFactoryBean;
-
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;
-
-
@Configuration
-
// // 掃描 Mapper接口
-
@MapperScan(value ="com.sunsharing.mapper" ,sqlSessionFactoryRef = "teacherSqlSessionFactory")
-
public
class TeacherDataSourceConfig {
-
-
-
@Bean(name = "teacherDataSource")
-
public DataSource masterDataSource() {
-
DruidXADataSource druidXADataSource = new DruidXADataSource();
-
druidXADataSource.setUrl(
"jdbc:mysql://localhost:3306/reactstu?useUnicode=true&characterEncoding=UTF8&useSSL=false");
-
druidXADataSource.setUsername(
"root");
-
druidXADataSource.setPassword(
"");
-
-
AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
-
atomikosDataSourceBean.setXaDataSource(druidXADataSource);
-
atomikosDataSourceBean.setUniqueResourceName(
"teacherDataSource");
-
atomikosDataSourceBean.setPoolSize(
5);
-
return atomikosDataSourceBean;
-
}
-
-
-
@Bean(name = "teacherSqlSessionFactory")
-
public SqlSessionFactory masterSqlSessionFactory(
@Qualifier("teacherDataSource") DataSource masterDataSource)
-
throws Exception {
-
final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
-
sessionFactory.setDataSource(masterDataSource);
-
return sessionFactory.getObject();
-
}
-
-
}
這里就不用配置JtaTransactionManager了。
測試:
-
@Autowired
-
MoviesMapper moviesMapper;
-
-
@Autowired
-
TeacherMapper teacherMapper;
-
-
-
@RequestMapping(method = RequestMethod.GET)
-
public MyResponseJson twodata() {
-
for (
int i =
0;i <
5;i++) {
-
if(i <
2) {
-
Teacher teacher =
new Teacher(
"3",
10);
-
teacherMapper.insertteacher(teacher);
-
Movies movies =
new Movies(
"3",
"3",
50,
10);
-
moviesMapper.insertmovies(movies);
-
-
}
else {
-
throw
new RuntimeException();
-
}
-
}
-
return
new MyResponseJson(
200,
"成功!",
null);
-
}
測試結果:可以回滾