springmvc atomikos mysql数据源_springboot+atomikos+多数据源管理事务(mysql 8.0)
jta:Java Transaction API,即是java中對(duì)事務(wù)處理的api?即?api即是接口的意思
atomikos:Atomikos TransactionsEssentials 是一個(gè)為Java平臺(tái)提供增值服務(wù)的并且開源類事務(wù)管理器
1.結(jié)構(gòu)
2.pom依賴
我這里使用本地?cái)?shù)據(jù)庫(kù)是mysql8,
org.springframework.boot
spring-boot-starter-parent
2.1.0.RELEASE
UTF-8
UTF-8
1.8
org.springframework.boot
spring-boot-starter-jdbc
org.springframework.boot
spring-boot-starter-web
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.3.0
org.springframework.boot
spring-boot-starter-jta-atomikos
org.springframework.boot
spring-boot-devtools
runtime
mysql
mysql-connector-java
8.0.13
org.projectlombok
lombok
true
1.18.2
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-configuration-processor
true
3.創(chuàng)建本地?cái)?shù)據(jù)庫(kù)+表
4.application.yml
server:
port: 8080
servlet:
# # 項(xiàng)目contextPath
context-path: /manyDatasource
spring:
application:
name: manyDatasource
datasource:
# spring.datasource.test1
# druid:
test1:
# jdbc-url,url,jdbcurl哪個(gè)合適用哪個(gè)
jdbcurl: jdbc:mysql://localhost:3306/test1?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
initial-size: 1
min-idle: 1
max-active: 20
test-on-borrow: true
# driver-class-name: com.mysql.jdbc.Driver
# 下面是最新的mysql8版本推薦的驅(qū)動(dòng)
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
# 下面是另外加的配置數(shù)據(jù)源的參數(shù)
minPoolSize: 3
maxPoolSize: 25
maxLifetime: 20000
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
test2:
jdbcurl: jdbc:mysql://localhost:3306/test2?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
minPoolSize: 3
maxPoolSize: 25
maxLifetime: 20000
borrowConnectionTimeout: 30
loginTimeout: 30
maintenanceInterval: 60
maxIdleTime: 60
mybatis:
mapper-locations: classpath:mapper/*.xml
#設(shè)置靜態(tài)資源路徑,多個(gè)以逗號(hào)分隔
spring.resources.static-locations: classpath:static/,file:static/
# 日志配置
logging:
level:
czs: debug
org.springframework: WARN
org.spring.springboot.dao: debug
5.實(shí)體類
ps.使用lombok插件挺方便的~ ?id數(shù)據(jù)庫(kù)主鍵自增
@Datapublic classUser {privateInteger id;privateString name;private longage;
}
6.mapper接口
UserMapper1:
public interfaceUserMapper1 {//查詢語(yǔ)句
@Select("SELECT * FROM users WHERE NAME = #{name}")
User findByName(@Param("name") String name);//添加
@Insert("INSERT INTO users(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);
}
UserMapper2:
public interfaceUserMapper2 {//查詢語(yǔ)句
@Select("SELECT * FROM users WHERE NAME = #{name}")
User findByName(@Param("name") String name);//添加
@Insert("INSERT INTO users(NAME, AGE) VALUES(#{name}, #{age})")int insert(@Param("name") String name, @Param("age") Integer age);
}
7.service
ManyService1:
@Servicepublic classManyService1 {
@AutowiredprivateUserMapper1 userMapper1;
@AutowiredprivateUserMapper2 userMapper2;/*@Transactional(transactionManager = "test1TransactionManager",rollbackFor = Exception.class)
public int insert(String name, Integer age) {
int i = userMapper1.insert(name, age);
System.out.println("userMapper1.insert結(jié)束~ :" + i);
// int a = 1 / 0;//手動(dòng)異常
return i;
}*/
//開啟事務(wù),由于使用jta+atomikos解決分布式事務(wù),所以此處不必再指定事務(wù)
@Transactionalpublic intinsert(String name, Integer age) {int insert =userMapper1.insert(name, age);//int i = 1 / age;//賦值age為0故意引發(fā)事務(wù)
returninsert;
}//http://localhost:8080/manyDatasource/insertDb1AndDb2?name=tom3&age=2//開啟事務(wù),由于使用jta+atomikos解決分布式事務(wù),所以此處不必再指定事務(wù)
@Transactionalpublic intinsertDb1AndDb2(String name, Integer age) {int insert =userMapper1.insert(name, age);int insert2 =userMapper2.insert(name, age);int i = 1 / age;//賦值age為0故意引發(fā)事務(wù)
return insert +insert2;
}
}
ManyService2:
@Servicepublic classManyService2 {
@AutowiredprivateUserMapper2 userMapper2;
@Transactional(transactionManager= "test2TransactionManager",rollbackFor = Exception.class)public intinsert(String name, Integer age) {int i =userMapper2.insert(name, age);
System.out.println("userMapper2.insert結(jié)束~ :" + null);int a = 1 / 0;//手動(dòng)異常
returni;
}
}
8.Controller
@RestControllerpublic classManyController {
@AutowiredprivateManyService1 manyService1;
@ResourceprivateManyService2 manyService2;
@RequestMapping(value= "datasource1")public intdatasource1(String name, Integer age) {returnmanyService1.insert(name, age);
}
@RequestMapping(value= "datasource2")public intdatasource2(String name, Integer age) {returnmanyService2.insert(name, age);
}/*** @Param:
* @Description: 這里測(cè)試兩個(gè)service兩個(gè)數(shù)據(jù)源的事務(wù)(不加上atomikos插件的情況下測(cè)試,
*使用DataSource1Config和DataSource2Config 兩個(gè)配置類, 關(guān)閉DBConfig1, DBConfig2和MyBatisConfig1, MyBatisConfig1兩個(gè)類)
* @Author: zyf 2019/5/10*/
//http://localhost:8080/manyDatasource/testManyTrans?name=tom4&age=2
@RequestMapping(value = "testManyTrans")public inttestManyTrans(String name, Integer age) {int i = 0;int i1 =manyService1.insert(name, age);
System.out.println("manyService1.insert :" +i1);/*第二個(gè)事務(wù)中會(huì)手動(dòng)造成一個(gè)異常~,
但是第一個(gè)事務(wù)執(zhí)行完畢了,保存到了數(shù)據(jù)庫(kù)*/
int i2 =manyService2.insert(name, age);
System.out.println("manyService2.insert :" +i2);returni;
}/*** @Param:
* @Description: 這里測(cè)試使用atomikos插件測(cè)試多數(shù)據(jù)源事務(wù)
* @Author: zyf 2019/5/10*/
//http://localhost:8080/manyDatasource/insertDb1AndDb2?name=tom5&age=2//http://localhost:8080/manyDatasource/insertDb1AndDb2?name=tom6&age=0//測(cè)試除數(shù)為0后的事務(wù)管理
@RequestMapping(value = "insertDb1AndDb2")public intinsertDb1AndDb2(String name, Integer age) {returnmanyService1.insertDb1AndDb2(name, age);
}
}
9.配置數(shù)據(jù)源(*******重點(diǎn)總是在最后********)
DBConfig1:
@Data
@ConfigurationProperties(prefix= "spring.datasource.test1") //注意這個(gè)前綴要和application.yml文件的前綴一樣
public classDBConfig1 {//@Value("${mysql.datasource.test1.jdbcurl}")//@Value("${jdbcurl}")
privateString jdbcurl;//private String url;//比如這個(gè)url在properties中是這樣子的mysql.datasource.test1.username = root
privateString username;privateString password;private intminPoolSize;private intmaxPoolSize;private intmaxLifetime;private intborrowConnectionTimeout;private intloginTimeout;private intmaintenanceInterval;private intmaxIdleTime;privateString testQuery;
}
DBConfig2:
@Data
@ConfigurationProperties(prefix= "spring.datasource.test2")//注意這個(gè)前綴要和application.yml文件的前綴一樣
public classDBConfig2 {//@Value("${spring.datasource.test2.jdbcurl}")//@Value("${jdbcurl}")//private String url;
privateString jdbcurl;privateString username;privateString password;private intminPoolSize;private intmaxPoolSize;private intmaxLifetime;private intborrowConnectionTimeout;private intloginTimeout;private intmaintenanceInterval;private intmaxIdleTime;privateString testQuery;
}
上面兩個(gè)配置類作用:?將application.yml配置文件中配置自動(dòng)封裝到實(shí)體類字段中,然后賦值給atomikos類型的數(shù)據(jù)源.(下面兩個(gè)具體配置數(shù)據(jù)源)
MyBatisConfig1:
//配置數(shù)據(jù)源//@Bean(name = "testDataSource")//test1DataSource
@Bean(name = "test1DataSource") //test1DataSource
public DataSource testDataSource(DBConfig1 testConfig) throwsSQLException {
MysqlXADataSource mysqlXaDataSource= newMysqlXADataSource();//mysqlXaDataSource.setUrl(testConfig.getUrl());
mysqlXaDataSource.setUrl(testConfig.getJdbcurl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(testConfig.getPassword());
mysqlXaDataSource.setUser(testConfig.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);//將本地事務(wù)注冊(cè)到創(chuàng) Atomikos全局事務(wù)
AtomikosDataSourceBean xaDataSource = newAtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("test1DataSource");
xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
xaDataSource.setTestQuery(testConfig.getTestQuery());returnxaDataSource;
}
@Bean(name= "test1SqlSessionFactory")public SqlSessionFactory testSqlSessionFactory(@Qualifier("test1DataSource") DataSource dataSource)throwsException {
SqlSessionFactoryBean bean= newSqlSessionFactoryBean();
bean.setDataSource(dataSource);returnbean.getObject();
}
@Bean(name= "test1SqlSessionTemplate")publicSqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test1SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throwsException {return newSqlSessionTemplate(sqlSessionFactory);
}
MyBatisConfig2 :
@Configuration
@MapperScan(basePackages= "czs.mapper2", sqlSessionTemplateRef = "test2SqlSessionTemplate")public classMyBatisConfig2 {//配置數(shù)據(jù)源
@Bean(name = "test2DataSource")public DataSource testDataSource(DBConfig2 testConfig) throwsSQLException {
MysqlXADataSource mysqlXaDataSource= newMysqlXADataSource();//mysqlXaDataSource.setUrl(testConfig.getUrl());
mysqlXaDataSource.setUrl(testConfig.getJdbcurl());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
mysqlXaDataSource.setPassword(testConfig.getPassword());
mysqlXaDataSource.setUser(testConfig.getUsername());
mysqlXaDataSource.setPinGlobalTxToPhysicalConnection(true);
AtomikosDataSourceBean xaDataSource= newAtomikosDataSourceBean();
xaDataSource.setXaDataSource(mysqlXaDataSource);
xaDataSource.setUniqueResourceName("test2DataSource");
xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
xaDataSource.setTestQuery(testConfig.getTestQuery());returnxaDataSource;
}
@Bean(name= "test2SqlSessionFactory")public SqlSessionFactory testSqlSessionFactory(@Qualifier("test2DataSource") DataSource dataSource)throwsException {
SqlSessionFactoryBean bean= newSqlSessionFactoryBean();
bean.setDataSource(dataSource);returnbean.getObject();
}
@Bean(name= "test2SqlSessionTemplate")publicSqlSessionTemplate testSqlSessionTemplate(
@Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throwsException {return newSqlSessionTemplate(sqlSessionFactory);
}
}
10.測(cè)試
http://localhost:8080/manyDatasource/insertDb1AndDb2?name=tom5&age=2
結(jié)果: test1和test2數(shù)據(jù)庫(kù)都插入數(shù)據(jù)~
http://localhost:8080/manyDatasource/insertDb1AndDb2?name=tom6&age=0 (兩個(gè)insert操作后,手動(dòng)異常)
結(jié)果: test1和test2數(shù)據(jù)庫(kù)都未插入數(shù)據(jù)~
GitHub傳送門: https://github.com/ColoZhu/springbootmanyDatasource
參考出處:?https://blog.csdn.net/qq_36138324/article/details/81612890
總結(jié)
以上是生活随笔為你收集整理的springmvc atomikos mysql数据源_springboot+atomikos+多数据源管理事务(mysql 8.0)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 控制台怎么退出mysql_退出mysql
- 下一篇: hp-ux mysql_HP-UX安装M