项目中需要数据库分布式事物的实现,于是采用了atumikos技术。

因为生产上需要稳定,所以采用了springboot 1.5.9.RELEASE版本。

本文代码gitlab下载地址: https://gitlab.com/atomikos/springBootMultDB-druidOracle.git

新建一个springboot项目,然后依次添加本文所有代码。我的项目结构如下:

1、pom.xml 代码

  1. <project xmlns="http://maven.apache.org/POM/4.0.0"
  2. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <groupId>springBootMultDB</groupId>
  6. <artifactId>springBootMultDB-druidOracle</artifactId>
  7. <version>0.0.1-SNAPSHOT</version>
  8. <packaging>jar</packaging>
  9. <name>springBootMultDB-druidOracle</name>
  10.  
  11. <parent>
  12. <groupId>org.springframework.boot</groupId>
  13. <artifactId>spring-boot-starter-parent</artifactId>
  14. <version>1.5.9.RELEASE</version>
  15. <relativePath />
  16. </parent>
  17. <properties>
  18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19. </properties>
  20.  
  21. <dependencies>
  22. <dependency>
  23. <groupId>junit</groupId>
  24. <artifactId>junit</artifactId>
  25. <version>3.8.1</version>
  26. <scope>test</scope>
  27. </dependency>
  28.  
  29. <dependency>
  30. <groupId>org.springframework.boot</groupId>
  31. <artifactId>spring-boot-starter-web</artifactId>
  32. <exclusions>
  33. <!-- 排除spring boot默认使用的tomcat,使用jetty -->
  34. <exclusion>
  35. <groupId>org.springframework.boot</groupId>
  36. <artifactId>spring-boot-starter-tomcat</artifactId>
  37. </exclusion>
  38. </exclusions>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.springframework.boot</groupId>
  42. <artifactId>spring-boot-starter-jetty</artifactId>
  43. </dependency>
  44. <dependency>
  45. <groupId>org.springframework.boot</groupId>
  46. <artifactId>spring-boot-starter-jdbc</artifactId>
  47. </dependency>
  48. <dependency>
  49. <groupId>org.mybatis.spring.boot</groupId>
  50. <artifactId>mybatis-spring-boot-starter</artifactId>
  51. <version>1.3.2</version>
  52. </dependency>
  53. <dependency>
  54. <groupId>com.alibaba</groupId>
  55. <artifactId>druid</artifactId>
  56. <version>1.1.12</version>
  57. </dependency>
  58. <dependency>
  59. <groupId>com.alibaba</groupId>
  60. <artifactId>druid-spring-boot-starter</artifactId>
  61. <version>1.1.10</version>
  62. </dependency>
  63. <dependency>
  64. <groupId>org.springframework.boot</groupId>
  65. <artifactId>spring-boot-starter-jta-atomikos</artifactId>
  66. </dependency>
  67. <dependency>
  68. <groupId>com.oracle</groupId>
  69. <artifactId>ojdbc6</artifactId>
  70. <version>11.2.0.4.0</version>
  71. </dependency>
  72. </dependencies>
  73. </project>

这里的ojdbc6的jar注意一下,不是maven中央库能够下载到的,所以需要去oracle官方下载驱动jar包:

https://www.oracle.com/technetwork/database/enterprise-edition/jdbc-112010-090769.html

下载好驱动jar包之后,cmd命令窗口进入jar包所在目录,执行mvn安装jar到本地repository库,mvn命令:

mvn install:install-file -Dfile=d:/java-jar/ojdbc6.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.4.0 -Dpackaging=jar

把-Dfile的参数替换成你本地的ojdbc6的目录即可。

-Dversion版本参数查看方法:打开ojdbc6.jar,进入META-INF,打开MANIFEST.MF,找到 Implementation-Version的值,我这里是: 11.2.0.4.0

2、application.properties配置

  1. server.port=8082
  2. spring.application.name=springBootMultDB-druidOracle
  3.  
  4. # Oracle 1
  5. spring.datasource.test1.url=jdbc:oracle:thin:@localhost:1521:orcl
  6. spring.datasource.test1.username=system
  7. spring.datasource.test1.password=ZHUwen12
  8.  
  9. spring.datasource.test1.minPoolSize = 3
  10. spring.datasource.test1.maxPoolSize = 25
  11. spring.datasource.test1.maxLifetime = 20000
  12. spring.datasource.test1.borrowConnectionTimeout = 30
  13. spring.datasource.test1.loginTimeout = 30
  14. spring.datasource.test1.maintenanceInterval = 60
  15. spring.datasource.test1.maxIdleTime = 60
  16. spring.datasource.test1.testQuery = select 1 from dual
  17.  
  18. # # Oracle 2
  19. spring.datasource.test2.url=jdbc:oracle:thin:@localhost:1521:orcl
  20. spring.datasource.test2.username=zhuwen
  21. spring.datasource.test2.password=ZHUwen12
  22. spring.datasource.test2.minPoolSize = 3
  23. spring.datasource.test2.maxPoolSize = 25
  24. #连接最大存活时间
  25. spring.datasource.test2.maxLifetime = 20000
  26. #获取连接失败重新获等待最大时间
  27. spring.datasource.test2.borrowConnectionTimeout = 30
  28. #登入超时
  29. spring.datasource.test2.loginTimeout = 30
  30. # 连接回收时间
  31. spring.datasource.test2.maintenanceInterval = 60
  32. #最大闲置时间,超过最小连接池连接的连接将将关闭
  33. spring.datasource.test2.maxIdleTime = 60
  34. spring.datasource.test2.testQuery = select 1 from dual

这里的oracle两个库配置,只有username不一样,在oracle里面,两个user可视为两个数据库。

3、App.java启动类

  1. package com.zhuguang;
  2.  
  3. import org.mybatis.spring.annotation.MapperScan;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.boot.SpringApplication;
  6. import org.springframework.boot.autoconfigure.SpringBootApplication;
  7. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  8.  
  9. import com.zhuguang.datasource.DBConfig1;
  10. import com.zhuguang.datasource.DBConfig2;
  11.  
  12. /**
  13. * 非常感谢腾讯课堂烛光学院的lisa老师
  14. * @author zhuwen
  15. *
  16. */
  17. @SpringBootApplication
  18. @EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class })
  19. @MapperScan(basePackages = { "com.zhuguang.mapper" })
  20. public class App {
  21. private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(App.class);
  22.  
  23. public static void main(String[] args) {
  24. SpringApplication.run(App.class, args);
  25. }
  26.  
  27. }

4、两个Oracle数据库配置类

  1. package com.zhuguang.datasource;
  2. import org.springframework.boot.context.properties.ConfigurationProperties;
  3. @ConfigurationProperties(prefix = "spring.datasource.test1")
  4. public class DBConfig1 {
  5.  
  6. private String url;
  7. private String username;
  8. private String password;
  9. private int minPoolSize;
  10. private int maxPoolSize;
  11. private int maxLifetime;
  12. private int borrowConnectionTimeout;
  13. private int loginTimeout;
  14. private int maintenanceInterval;
  15. private int maxIdleTime;
  16. private String testQuery;
  17.  
  18. getter and setter...
  19. }

第二个数据库配置类与DBConfig1一样,唯一不同的地方在于 prefix = "spring.datasource.test2",类名叫DBConfig2

  1. 5atomikos分布式数据源配置类
    TestMyBatisConfig1
  1. package com.zhuguang.datasource;
  2. import java.sql.SQLException;
  3. import javax.sql.DataSource;
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.mybatis.spring.SqlSessionFactoryBean;
  6. import org.mybatis.spring.SqlSessionTemplate;
  7. import org.mybatis.spring.annotation.MapperScan;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.beans.factory.annotation.Qualifier;
  10. import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
  11. import org.springframework.context.annotation.Bean;
  12. import org.springframework.context.annotation.Configuration;
  13. import org.springframework.context.annotation.Primary;
  14. import com.alibaba.druid.pool.xa.DruidXADataSource;
  15. @Configuration
  16. // basePackages 最好分开配置 如果放在同一个文件夹可能会报错
  17. @MapperScan(basePackages = "com.zhuguang.db1", sqlSessionTemplateRef = "testSqlSessionTemplate")
  18. public class TestMyBatisConfig1 {
  19. private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestMyBatisConfig1.class);
  20.  
  21. // 配置数据源
  22. @Primary
  23. @Bean(name = "dataSource1")
  24. public DataSource testDataSource(DBConfig1 testConfig) throws SQLException {
  25. //Atomikos统一管理分布式事务
  26. AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
  27.  
  28. // Properties p = new Properties();
  29. // p.setProperty ( "user" , testConfig.getUsername() );
  30. // p.setProperty ( "password" , testConfig.getPassword() );
  31. // p.setProperty ( "URL" , testConfig.getUrl() );
  32. // xaDataSource.setXaProperties ( p );
  33.  
  34. //用druidXADataSource方式或者上面的Properties方式都可以
  35. DruidXADataSource druidXADataSource = new DruidXADataSource();
  36. druidXADataSource.setUrl(testConfig.getUrl());
  37. druidXADataSource.setUsername(testConfig.getUsername());
  38. druidXADataSource.setPassword(testConfig.getPassword());
  39.  
  40. xaDataSource.setUniqueResourceName("oracle1");
  41. xaDataSource.setXaDataSource(druidXADataSource);
  42. xaDataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
  43. xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
  44. xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
  45. xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
  46. xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
  47. xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
  48. xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
  49. xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
  50. xaDataSource.setTestQuery(testConfig.getTestQuery());
  51.  
  52. LOG.info("分布式事物dataSource1实例化成功");
  53. return xaDataSource;
  54. }
  55.  
  56. @Primary
  57. @Bean(name = "testSqlSessionFactory")
  58. public SqlSessionFactory testSqlSessionFactory(@Qualifier("dataSource1") DataSource dataSource)
  59. throws Exception {
  60. SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
  61. bean.setDataSource(dataSource);
  62. return bean.getObject();
  63. }
  64.  
  65. @Primary
  66. @Bean(name = "testSqlSessionTemplate")
  67. public SqlSessionTemplate testSqlSessionTemplate(
  68. @Qualifier("testSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
  69. return new SqlSessionTemplate(sqlSessionFactory);
  70. }
  71. }

再建一个一模一样的TestMyBatisConfig1类,取名叫TestMyBatisConfig2,不同的地方是注解和bean命名:

  1. package com.zhuguang.datasource;
  2. import java.sql.SQLException;
  3. import java.util.Properties;
  4. import javax.sql.DataSource;
  5. import org.apache.ibatis.session.SqlSessionFactory;
  6. import org.mybatis.spring.SqlSessionFactoryBean;
  7. import org.mybatis.spring.SqlSessionTemplate;
  8. import org.mybatis.spring.annotation.MapperScan;
  9. import org.slf4j.LoggerFactory;
  10. import org.springframework.beans.factory.annotation.Qualifier;
  11. import org.springframework.context.annotation.Bean;
  12. import org.springframework.context.annotation.Configuration;
  13. import com.alibaba.druid.pool.xa.DruidXADataSource;
  14. import com.atomikos.jdbc.AtomikosDataSourceBean;
  15. import oracle.jdbc.xa.client.OracleXADataSource;
  16. // basePackages 最好分开配置 如果放在同一个文件夹可能会报错
  17. @Configuration
  18. @MapperScan(basePackages = "com.zhuguang.db2", sqlSessionTemplateRef = "test2SqlSessionTemplate")
  19. public class TestMyBatisConfig2 {
  20. private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(TestMyBatisConfig2.class);
  21.  
  22. // 配置数据源
  23. @Bean(name = "dataSource2")
  24. public DataSource testDataSource(DBConfig2 testConfig) throws SQLException {
  25. AtomikosDataSourceBean xaDataSource = new AtomikosDataSourceBean();
  26.  
  27. // Properties p = new Properties();
  28. // p.setProperty ( "user" , testConfig.getUsername() );
  29. // p.setProperty ( "password" , testConfig.getPassword() );
  30. // p.setProperty ( "URL" , testConfig.getUrl() );
  31. // xaDataSource.setXaProperties ( p );
  32.  
  33. //用druidXADataSource方式或者上面的Properties方式都可以
  34. DruidXADataSource druidXADataSource = new DruidXADataSource();
  35. druidXADataSource.setUrl(testConfig.getUrl());
  36. druidXADataSource.setUsername(testConfig.getUsername());
  37. druidXADataSource.setPassword(testConfig.getPassword());
  38.  
  39. xaDataSource.setUniqueResourceName("oracle2");
  40. xaDataSource.setXaDataSource(druidXADataSource);
  41. xaDataSource.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
  42. xaDataSource.setMaxLifetime(testConfig.getMaxLifetime());
  43. xaDataSource.setMinPoolSize(testConfig.getMinPoolSize());
  44. xaDataSource.setMaxPoolSize(testConfig.getMaxPoolSize());
  45. xaDataSource.setBorrowConnectionTimeout(testConfig.getBorrowConnectionTimeout());
  46. xaDataSource.setLoginTimeout(testConfig.getLoginTimeout());
  47. xaDataSource.setMaintenanceInterval(testConfig.getMaintenanceInterval());
  48. xaDataSource.setMaxIdleTime(testConfig.getMaxIdleTime());
  49. xaDataSource.setTestQuery(testConfig.getTestQuery());
  50.  
  51. LOG.info("分布式事物dataSource2实例化成功");
  52. return xaDataSource;
  53. }
  54.  
  55. @Bean(name = "test2SqlSessionFactory")
  56. public SqlSessionFactory testSqlSessionFactory(@Qualifier("dataSource2") DataSource dataSource)
  57. throws Exception {
  58. SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
  59. bean.setDataSource(dataSource);
  60. return bean.getObject();
  61. }
  62.  
  63. @Bean(name = "test2SqlSessionTemplate")
  64. public SqlSessionTemplate testSqlSessionTemplate(
  65. @Qualifier("test2SqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
  66. return new SqlSessionTemplate(sqlSessionFactory);
  67. }
  68. }

6、为两个数据库分别建立USERS表

首先在两个Oracle数据库里都建立表:

  1. CREATE TABLE users (
  2. name varchar2(20 BYTE),
  3. age NUMBER(*,0)
  4. );

并建立entity:

  1. package com.zhuguang.entity;
  2. public class Users {
  3. private String id;
  4. private String name;
  5. private Integer age;
  6.  
  7. getter and setter..
  8. }

7、为users建立mapper类

  1. package com.zhuguang.db1.dao;
  2.  
  3. import java.util.List;
  4. import org.apache.ibatis.annotations.Delete;
  5. import org.apache.ibatis.annotations.Insert;
  6. import org.apache.ibatis.annotations.Param;
  7. import org.apache.ibatis.annotations.Select;
  8. import com.zhuguang.entity.Users;
  9.  
  10. public interface DB1_UserMapper {
  11. @Select("SELECT * FROM USERS WHERE NAME = #{name}")
  12. Users findByName(@Param("name") String name);
  13.  
  14. @Insert("INSERT INTO USERS(NAME, AGE) VALUES(#{name}, #{age})")
  15. int insert(@Param("name") String name, @Param("age") Integer age);
  16.  
  17. @Delete("Delete from USERS")
  18. void deleteAll();
  19.  
  20. @Select("select 'oracle1' as id,t.* from USERS t")
  21. List<Users> queryAll();
  22. }
  1. package com.zhuguang.db2.dao;
  2.  
  3. import java.util.List;
  4. import org.apache.ibatis.annotations.Delete;
  5. import org.apache.ibatis.annotations.Insert;
  6. import org.apache.ibatis.annotations.Param;
  7. import org.apache.ibatis.annotations.Select;
  8. import com.zhuguang.entity.Users;
  9.  
  10. //test1 DB
  11. public interface DB2_UserMapper {
  12. @Select("SELECT * FROM USERS WHERE NAME = #{name}")
  13. Users findByName(@Param("name") String name);
  14.  
  15. @Insert("INSERT INTO USERS(NAME, AGE) VALUES(#{name}, #{age})")
  16. int insert(@Param("name") String name, @Param("age") Integer age);
  17.  
  18. /**
  19. * 用于演示插入数据库异常的情况
  20. */
  21. @Insert("INSERT INTO not_exists_table_USERS(NAME, AGE) VALUES(#{name}, #{age})")
  22. int insertNotExistsTable(@Param("name") String name, @Param("age") Integer age);
  23.  
  24. @Delete("Delete from USERS")
  25. void deleteAll();
  26.  
  27. @Select("select 'oracle2' as id,t.* from USERS t")
  28. List<Users> queryAll();
  29. }

8、建立Controller

  1. package com.zhuguang.controller;
  2.  
  3. import java.util.Date;
  4. import java.util.List;
  5. import javax.annotation.Resource;
  6. import javax.sql.DataSource;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.beans.factory.annotation.Qualifier;
  11. import org.springframework.web.bind.annotation.RequestMapping;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import com.zhuguang.db1.service.DB1_UserService;
  14. import com.zhuguang.db2.service.DB2_UserService;
  15. import com.zhuguang.service.IndexService;
  16. /**
  17. * 感谢腾讯课堂烛光学院lisa老师
  18. * @author zhuwen
  19. *
  20. */
  21. @RestController
  22. public class IndexController {
  23. private static Logger log = LoggerFactory.getLogger(IndexController.class);
  24.  
  25. @Autowired
  26. private DB1_UserService userService1;
  27. @Autowired
  28. private DB2_UserService userService2;
  29. @Autowired
  30. private IndexService indexService;
  31.  
  32. //想查看数据源,可以这么注解
  33. @Resource
  34. @Qualifier("dataSource1")
  35. private DataSource dataSource1;
  36.  
  37. @RequestMapping("/insertDB1")
  38. public String insertTest001(String name, Integer age) {
  39. // userMapperTest01.insert(name, age);
  40. userService1.insertDB1(name, age);
  41. return "success insertDB1";
  42. }
  43.  
  44. @RequestMapping("/insertDB2")
  45. public String insertTest002(String name, Integer age) {
  46. userService2.insertDB2(name, age);
  47. return "success insertDB2";
  48. }
  49.  
  50. /**
  51. * atomikos效果:分布式事物。两个数据库都插入值
  52. *
  53. * @param name
  54. * @param age
  55. * @return
  56. */
  57. @RequestMapping("/insertTwoDBs")
  58. public String insertTwoDBs(String name, Integer age) {
  59. indexService.insertTwoDBs(name, age);
  60. return "success insertTwoDBs";
  61. }
  62.  
  63. /**
  64. * atomikos效果:分布式事物。 演示发生异常分布式事物回滚
  65. *
  66. * @param name
  67. * @param age
  68. * @return
  69. */
  70. @RequestMapping("/insertTwoDBsWithError")
  71. public String insertTwoDBsWithError(String name, Integer age) {
  72. indexService.insertTwoDBsWithError(name, age);
  73. return "success insertTwoDBs";
  74. }
  75.  
  76. /**
  77. * atomikos效果:分布式事物。 演示发生异常分布式事物回滚
  78. * 直接调用mapper方式
  79. * @param name
  80. * @param age
  81. * @return
  82. */
  83. @RequestMapping("/insertTwoDBsUseMapperWithError")
  84. public String insertTwoDBsUseMapperWithError(String name, Integer age) {
  85. indexService.insertTwoDBsUseMapperWithError(name, age);
  86. return "success insertTwoDBsUseMapperWithError";
  87. }
  88.  
  89. /**
  90. * 获取两个数据库的所有数据
  91. * @return
  92. */
  93. @RequestMapping("/queryAll")
  94. public List queryAll() {
  95. List list = indexService.queryAll();
  96. list.add(new Date().toLocaleString()); //加上时间戳,方便postman观察结果
  97. return list;
  98. }
  99.  
  100. /**
  101. * 删除两个数据库的所有数据
  102. * @return
  103. */
  104. @RequestMapping("/deleteAll")
  105. public String deleteAll() {
  106. indexService.deleteAll();
  107. return "success delete all";
  108. }
  109.  
  110. }

9、建立service

  1. package com.zhuguang.service;
  2.  
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.stereotype.Service;
  7. import org.springframework.transaction.annotation.Transactional;
  8. import org.springframework.util.CollectionUtils;
  9. import com.zhuguang.db1.dao.DB1_UserMapper;
  10. import com.zhuguang.db1.service.DB1_UserService;
  11. import com.zhuguang.db2.dao.DB2_UserMapper;
  12. import com.zhuguang.db2.service.DB2_UserService;
  13. import com.zhuguang.entity.Users;
  14.  
  15. @Service
  16. public class IndexService {
  17. @Autowired
  18. private DB1_UserMapper db1UserMapper;
  19. @Autowired
  20. private DB2_UserMapper db2UserMapper;
  21. @Autowired
  22. private DB1_UserService db1UserService;
  23. @Autowired
  24. private DB2_UserService db2UserService;
  25. /**
  26. * atomikos效果:分布式事物。两个数据库都插入值
  27. * @return
  28. */
  29. @Transactional
  30. public void insertTwoDBs(String name, Integer age) {
  31. db1UserMapper.insert(name, age);
  32. db2UserMapper.insert(name, age);
  33. }
  34.  
  35. @Transactional
  36. public void deleteAll() {
  37. db1UserMapper.deleteAll();
  38. //不同数据库。test1,test2
  39. //userService2.insertDB2(name, age);
  40. db2UserMapper.deleteAll();//test2
  41. // int i = 1 / 0;//
  42. }
  43.  
  44. /**
  45. * atomikos效果:分布式事物。
  46. * 演示发生异常分布式事物回滚
  47. * 这里无论error 1、2、3,任何一处发生异常,分布式事物都会回滚
  48. */
  49. @Transactional //(rollbackFor = { Exception.class })
  50. public void insertTwoDBsWithError(String name, Integer age) {
  51. db1UserService.insert2DB1(name, age);
  52. db2UserService.insert2DB2(name, age);
  53. //int i = 1 / 0; // error 1
  54. }
  55.  
  56. /**
  57. * atomikos效果:分布式事物。
  58. * 演示发生异常分布式事物回滚
  59. * 这里无论error 1、2、3,任何一处发生异常,分布式事物都会回滚
  60. * 此方法效果等同于insertTwoDBsWithError
  61. */
  62. @Transactional
  63. public void insertTwoDBsUseMapperWithError(String name, Integer age) {
  64. db1UserMapper.insert(name, age);
  65. db2UserMapper.insert(name, age);
  66. db2UserMapper.insertNotExistsTable(name, age);
  67. }
  68.  
  69. public List queryAll() {
  70. List all = new ArrayList();
  71.  
  72. List<Users> list1 = db1UserService.queryAll();
  73. if(CollectionUtils.isEmpty(list1)) {
  74. all.add("db1 没有任何数据!");
  75. }else {
  76. all.addAll(list1);
  77. }
  78.  
  79. List<Users> list2 = db2UserService.queryAll();
  80. if(CollectionUtils.isEmpty(list2)) {
  81. all.add("db2 没有任何数据!");
  82. }else {
  83. all.addAll(list2);
  84. }
  85.  
  86. return all;
  87. }
  88.  
  89. }

10、使用postman验证

主要验证:/insertTwoDBsUseMapperWithError 这个效果,是否任何一处DB产生错误,都会使分布式事物回滚。

11、druid监控页面

启动App.java之后,只要在浏览器里输入http://localhost:8082/druid/index.html就可以进入druid监控页面:

但是由于这里使用的是atomikos分布式事物DataSource,不是原本的druidDataSource,所以这里几乎监控不到任何有价值的东西,基本作废。

end.

SpringBoot集成Atomikos使用Oracle数据库mybatis、jta框架的更多相关文章

  1. springboot集成liquibase,h2数据库

    Liquibase是一个用于跟踪.管理和应用数据库变化的开源的数据库重构工具.它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制. Liquibase具备如下特性:* 不依赖于特 ...

  2. Oracle数据库mybatis 插入空值时报错(with JdbcType OTHER)

    参考文档: 1.https://blog.csdn.net/fishernemo/article/details/27649233 2.http://helgaxu.iteye.com/blog/21 ...

  3. springboot集成jpa,在postgresql数据库中创建主键自增表

    依赖文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:/ ...

  4. Oracle数据库——Mybatis在一个update标签下执行多更新语句

    begin update table table1 set com1 ='1' ; update table table2 set com1 ='1' ; end;

  5. SpringBoot集成mybatis,同时读取一个数据库中多个数据表

    SpringBoot集成mybatis,同时读取一个数据库中多个数据表: application.properties: mybatis.config-location=classpath:mybat ...

  6. SpringBoot 集成Mybatis 连接Mysql数据库

    记录SpringBoot 集成Mybatis 连接数据库 防止后面忘记 1.添加Mybatis和Mysql依赖 <dependency> <groupId>org.mybati ...

  7. SpringBoot集成MyBatis的分页插件 PageHelper

    首先说说MyBatis框架的PageHelper插件吧,它是一个非常好用的分页插件,通常我们的项目中如果集成了MyBatis的话,几乎都会用到它,因为分页的业务逻辑说复杂也不复杂,但是有插件我们何乐而 ...

  8. springBoot 集成Mysql数据库

    springBoot 集成Mysql数据库 前一段时间,我们大体介绍过SpringBoot,想必大家还有依稀的印象.我们先来回顾一下:SpringBoot是目前java世界最流行的一个企业级解决方案框 ...

  9. springboot集成redis(mybatis、分布式session)

    安装Redis请参考:<CentOS快速安装Redis> 一.springboot集成redis并实现DB与缓存同步 1.添加redis及数据库相关依赖(pom.xml) <depe ...

随机推荐

  1. ABP框架(asp.net core 2.X+Vue)模板项目学习之路(二)--切换MySql数据库

    前言: 大家好,今天给大家带来ABP第二篇的分享,在写这篇分享的时候非常的困难,因为发现ABP的框架越是深入.难度也就越大,而且深刻感觉到自己领域驱动开发知识的欠缺,前段时间买了两本有关于领域驱动知识 ...

  2. asp.net,根据gridview 中checkbox复选框选中的行对数据库进行操作

    在asp.net中,使用checkbox,对gridview添加复选框. 多选数据行后,根据已选数据,对原数据进行多条语句查询. string sql = "Select * from 表 ...

  3. 显示react配置

    1. 由于react默认隐藏webpack配置需要手动显示. npm run eject //Are you sure you want to eject? This action is perman ...

  4. Linux中使用sed命令替换字符串小结

    sed替换的基本语法为: sed 's/原字符串/替换字符串/' 单引号里面,s表示替换,三根斜线中间是替换的样式,特殊字符需要使用反斜线”\”进行转义,但是单引号”‘”是没有办法用反斜线”\”转义的 ...

  5. 爱因斯坦求和约定 (Einstein summation convention)

  6. Dapp的PVP发模式--magic-maze-2d游戏解读

    前言: 未来基于Dapp的游戏可能会多起来吧, 尤其是博彩类游戏, 由于区块链匿名特性, 加之数字货币不受国家监控, 几乎成了一个法外之地. 大量游戏团队都往之涌入. 今天讲讲当前Dapp的一种游戏模 ...

  7. Fiddler实现手机抓包——小白入门

    方法1:https://www.cnblogs.com/hzg1981/p/5610530.html 方法2:转载自:http://blog.csdn.net/gld824125233/article ...

  8. 计算机基础-C语言-16章-数组应用-计算字符串长度

    字符数组的大小并不代表它所包含字符串的长度.需要通过检查结束符,才能判断字符串的实际长度. 数组和指针的关系

  9. python中random模块的使用

    import random random.random() 产生0-1间的随机小数 >>> res = random.random() >>> print(res) ...

  10. cms建站

    1. 搭建php环境 phpnow软件安装(下载地址:  http://www.phpnow.org) 注意如果安装失败,请用以下解决办法: 1.请使用命令提示符(管理员)2.打开后进入PHPnow目 ...