环境
  eclipse 4.7
  jdk 1.8
  Spring Boot 1.5.2

一、springboot整合事务
事务分类:编程事务、声明事务(XML、注解),推荐使用注解方式,springboot默认集成事物,只主要在方法上加上@Transactional即可
1、controller

package com.wjy.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.wjy.test1.service.UserServiceTest1; @RestController
public class UserController { @Autowired
public UserServiceTest1 userServiceTest1; @RequestMapping("/insertTest1ByService")
public String insertTest1ByService(String name,Integer age) {
userServiceTest1.insertuser1(name, age);
return "success";
} }

2、service

/**
*
*/
package com.wjy.test1.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.wjy.test1.dao.UserMapperTest1; /**
* @Desc
* @author wangjy15
*/
@Service
public class UserServiceTest1 { @Autowired
private UserMapperTest1 userMapperTest1; /**
* @Description: 如果没有事务控制 那么报错之后 插入到库里的数据不会回滚 加上 注解@Transactional 就可以回滚
*/
@Transactional
public String insertuser1(String name,Integer age) {
userMapperTest1.insert(name, age);
int i =1/0;
return "success";
} }

3、mapper

/**
*
*/
package com.wjy.test1.dao; import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; import com.wjy.entity.User; /**
* @Desc
* @author wangjy15
*/
public interface UserMapperTest1 { @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);
}

4、APP

package com.wjy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class APP { public static void main(String[] args) {
SpringApplication.run(APP.class, args);
} }

5、测试验证

http://localhost:8080/insertTest1ByService?name=wangsan0010&age=1000

二、SpringBoot分布式事务管理

使用springboot+jta+atomikos分布式事务管理,service层有事务控制,dao层没有,一般情况下都需要调用其他数据源的dao层,这就需要进行分布式事务管理。
将多个数据源注册到atomikos进行管理,进行2PC(Two-phaseCommit)二阶段提交。

理解一下分布式事务:

对于上面一中示例做一下修改,再引入一个数据源test2,修改一下service:

/**
*
*/
package com.wjy.test1.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.wjy.test1.dao.UserMapperTest1;
import com.wjy.test2.dao.UserMapperTest2;
import com.wjy.test2.service.UserServiceTest2; /**
* @Desc
* @author wangjy15
*/
@Service
public class UserServiceTest1 { @Autowired
private UserMapperTest1 userMapperTest1; @Autowired
private UserMapperTest2 userMapperTest2; @Autowired
private UserServiceTest2 userServiceTest1; /**
* @Desc: 如果没有事务控制 那么报错之后 插入到库里的数据不会回滚 加上 注解@Transactional 就可以回滚
*/
@Transactional
public String insertuser1(String name,Integer age) {
userMapperTest1.insert(name, age);
userServiceTest1.insertuser2(name, age);//有事务控制 可以回滚
int i =1/0;
return "success";
} }
/**
*
*/
package com.wjy.test2.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional; import com.wjy.test2.dao.UserMapperTest2; /**
* @Desc
* @author wangjy15
*/
public class UserServiceTest2 {
@Autowired
private UserMapperTest2 userMapperTest2; /**
* @Desc: 如果没有事务控制 那么报错之后 插入到库里的数据不会回滚 加上 注解@Transactional 就可以回滚
*/
@Transactional
public String insertuser2(String name,Integer age) {
userMapperTest2.insert(name, age);
return "success";
} }

这时test1数据库里没有插入数据,test2数据库也没有插入数据库,因为test2在service层也有事务控制。

再修改一下test1 service:

/**
*
*/
package com.wjy.test1.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.wjy.test1.dao.UserMapperTest1;
import com.wjy.test2.dao.UserMapperTest2;
import com.wjy.test2.service.UserServiceTest2; /**
* @Desc
* @author wangjy15
*/
@Service
public class UserServiceTest1 { @Autowired
private UserMapperTest1 userMapperTest1; @Autowired
private UserMapperTest2 userMapperTest2;
/**
* @Desc: 如果没有事务控制 那么报错之后 插入到库里的数据不会回滚 加上 注解@Transactional 就可以回滚
*/
@Transactional
public String insertuser1(String name,Integer age) {
userMapperTest1.insert(name, age);
userMapperTest2.insert(name, age);//没有事务控制 不可以回滚 int i =1/0;
return "success";
} }

这时test1数据库里没有插入数据,test2数据库有数据插入到数据库  没有回滚,因为test2在mapper层也没有事务控制。

下面引入atomikos  和springboot整合:

1、数据源配置信息

引入依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
# Mysql 1
mysql.datasource.test1.url = jdbc:mysql://192.168.118.102:3306/springboot?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf-8
mysql.datasource.test1.username = root
mysql.datasource.test1.password = 123456 mysql.datasource.test1.minPoolSize = 3
mysql.datasource.test1.maxPoolSize = 25
mysql.datasource.test1.maxLifetime = 20000
mysql.datasource.test1.borrowConnectionTimeout = 30
mysql.datasource.test1.loginTimeout = 30
mysql.datasource.test1.maintenanceInterval = 60
mysql.datasource.test1.maxIdleTime = 60
mysql.datasource.test1.testQuery = select 1 # Mysql 2
mysql.datasource.test2.url =jdbc:mysql://192.168.118.102:3306/springboot2?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=utf-8
mysql.datasource.test2.username =root
mysql.datasource.test2.password =123456 mysql.datasource.test2.minPoolSize = 3
mysql.datasource.test2.maxPoolSize = 25
mysql.datasource.test2.maxLifetime = 20000
mysql.datasource.test2.borrowConnectionTimeout = 30
mysql.datasource.test2.loginTimeout = 30
mysql.datasource.test2.maintenanceInterval = 60
mysql.datasource.test2.maxIdleTime = 60
mysql.datasource.test2.testQuery = select 1

2、数据源配置类

package com.wjy.datasource;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix="mysql.datasource.test1")
public class DBConfig1 { private String url;
private String username;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getMinPoolSize() {
return minPoolSize;
}
public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getMaxLifetime() {
return maxLifetime;
}
public void setMaxLifetime(int maxLifetime) {
this.maxLifetime = maxLifetime;
}
public int getBorrowConnectionTimeout() {
return borrowConnectionTimeout;
}
public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
this.borrowConnectionTimeout = borrowConnectionTimeout;
}
public int getLoginTimeout() {
return loginTimeout;
}
public void setLoginTimeout(int loginTimeout) {
this.loginTimeout = loginTimeout;
}
public int getMaintenanceInterval() {
return maintenanceInterval;
}
public void setMaintenanceInterval(int maintenanceInterval) {
this.maintenanceInterval = maintenanceInterval;
}
public int getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
public String getTestQuery() {
return testQuery;
}
public void setTestQuery(String testQuery) {
this.testQuery = testQuery;
} }
package com.wjy.datasource;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix="mysql.datasource.test2")
public class DBConfig2 {
private String url;
private String username;
private String password;
private int minPoolSize;
private int maxPoolSize;
private int maxLifetime;
private int borrowConnectionTimeout;
private int loginTimeout;
private int maintenanceInterval;
private int maxIdleTime;
private String testQuery; public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getMinPoolSize() {
return minPoolSize;
}
public void setMinPoolSize(int minPoolSize) {
this.minPoolSize = minPoolSize;
}
public int getMaxPoolSize() {
return maxPoolSize;
}
public void setMaxPoolSize(int maxPoolSize) {
this.maxPoolSize = maxPoolSize;
}
public int getMaxLifetime() {
return maxLifetime;
}
public void setMaxLifetime(int maxLifetime) {
this.maxLifetime = maxLifetime;
}
public int getBorrowConnectionTimeout() {
return borrowConnectionTimeout;
}
public void setBorrowConnectionTimeout(int borrowConnectionTimeout) {
this.borrowConnectionTimeout = borrowConnectionTimeout;
}
public int getLoginTimeout() {
return loginTimeout;
}
public void setLoginTimeout(int loginTimeout) {
this.loginTimeout = loginTimeout;
}
public int getMaintenanceInterval() {
return maintenanceInterval;
}
public void setMaintenanceInterval(int maintenanceInterval) {
this.maintenanceInterval = maintenanceInterval;
}
public int getMaxIdleTime() {
return maxIdleTime;
}
public void setMaxIdleTime(int maxIdleTime) {
this.maxIdleTime = maxIdleTime;
}
public String getTestQuery() {
return testQuery;
}
public void setTestQuery(String testQuery) {
this.testQuery = testQuery;
} }
package com.wjy.datasource;

import java.sql.SQLException;

import javax.sql.DataSource;

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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; ////注册到springboot容器中
@Configuration
////@MapperScan可以指定要扫描的Mapper类的包的路径 sqlSessionFactoryRef 表示定义了 key ,表示一个唯一 SqlSessionFactory 实例
@MapperScan(basePackages="com.wjy.test1",sqlSessionFactoryRef="sqlSessionFactory1")
public class TestMyBatisConfig1 { @Bean(name="dataSource1")
@Primary
public DataSource dataSource1(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("dataSource1"); 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;
} //注意 这里没有事务管理类 因为事务全部交给AtomikosDataSourceBean来管理 @Primary
@Bean(name = "sqlSessionFactory1")
public SqlSessionFactory sqlSessionFactory1(@Qualifier("dataSource1") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
} @Primary
@Bean(name = "sqlSessionTemplate1")
public SqlSessionTemplate sqlSessionTemplate1(
@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
} }
package com.wjy.datasource;

import java.sql.SQLException;

import javax.sql.DataSource;

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.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import com.atomikos.jdbc.AtomikosDataSourceBean;
import com.mysql.jdbc.jdbc2.optional.MysqlXADataSource; @Configuration
@MapperScan(basePackages="com.wjy.test2",sqlSessionFactoryRef="sqlSessionFactory2")
public class TestMyBatisConfig2 { @Bean(name="dataSource2")
public DataSource dataSource2(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("dataSource2"); xaDataSource.setMinPoolSize(dbConfig2.getMinPoolSize());
xaDataSource.setMaxPoolSize(dbConfig2.getMaxPoolSize());
xaDataSource.setMaxLifetime(dbConfig2.getMaxLifetime());
xaDataSource.setBorrowConnectionTimeout(dbConfig2.getBorrowConnectionTimeout());
xaDataSource.setLoginTimeout(dbConfig2.getLoginTimeout());
xaDataSource.setMaintenanceInterval(dbConfig2.getMaintenanceInterval());
xaDataSource.setMaxIdleTime(dbConfig2.getMaxIdleTime());
xaDataSource.setTestQuery(dbConfig2.getTestQuery());
return xaDataSource;
} //注意 这里没有事务管理类 因为事务全部交给AtomikosDataSourceBean来管理 @Bean(name = "sqlSessionFactory2")
public SqlSessionFactory sqlSessionFactory2(@Qualifier("dataSource2") DataSource dataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
return bean.getObject();
} @Bean(name = "sqlSessionTemplate2")
public SqlSessionTemplate sqlSessionTemplate2(
@Qualifier("sqlSessionFactory2") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}

3、controller

package com.wjy.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.wjy.test1.service.UserServiceTest1; @RestController
public class UserController { @Autowired
public UserServiceTest1 userServiceTest1; @RequestMapping("/insertTest1ByService")
public String insertTest1ByService(String name,Integer age) {
userServiceTest1.insertuser1(name, age);
return "success";
} }

4、service

/**
*
*/
package com.wjy.test1.service; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import com.wjy.test1.dao.UserMapperTest1;
import com.wjy.test2.dao.UserMapperTest2; /**
* @Desc
* @author wangjy15
*/
@Service
public class UserServiceTest1 { @Autowired
private UserMapperTest1 userMapperTest1; @Autowired
private UserMapperTest2 userMapperTest2; /**
* @Desc: 如果没有事务控制 那么报错之后 插入到库里的数据不会回滚 加上 注解@Transactional 就可以回滚
*/
@Transactional
public String insertuser1(String name,Integer age) {
userMapperTest1.insert(name, age);
userMapperTest2.insert(name, age);//没有事务控制 不可以回滚 int i =1/0;
return "success";
} }

5、APP

package com.wjy;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import com.wjy.datasource.DBConfig1;
import com.wjy.datasource.DBConfig2; @SpringBootApplication
@EnableConfigurationProperties(value = { DBConfig1.class, DBConfig2.class }) //启动的时候读取两个类对应的配置信息
public class APP { public static void main(String[] args) {
SpringApplication.run(APP.class, args);
} }

6、测试验证

http://localhost:8080/insertTest1ByService?name=wangsan&age=10

执行后  两个数据库里都没有数据

最新文章

  1. plist文件的读取和xib加载cell
  2. 备受SQL青睐的“1”
  3. 使用后缀数组寻找最长公共子字符串JavaScript版
  4. PHP 文件与文件夹的创建和删除操作
  5. 工作空间项目不存在,eclipse中项目删不掉
  6. redis运用连接池报错解决
  7. 怎样搭建本地svn服务器环境-轻松掌握版本管理
  8. Android图像处理之Bitmap类(zz)
  9. &lt;q&gt;标签,短文本引用
  10. 浅谈Android序列化
  11. 你好,C++(21)只要天还没黑,就一直在工地干活-4.3.1 while循环:只要…就一直…
  12. 查询rman备份信息经常使用指令
  13. ActionContext、ServletContext、pageContext的区别?
  14. 【LeetCode】66. Plus One
  15. WebSphere--安装与配置
  16. 《An Industrial-Strength Audio Search Algorithm》译文
  17. day 7-6 GIL,死锁,递归锁与信号量,Event,queue,
  18. Runtime之实例总结
  19. MySQL之视图、触发器、事务、存储、函数、流程控制
  20. [深入Maven源代码]maven绑定命令行参数到具体插件

热门文章

  1. 【Postgres】Windows2012 不能启动
  2. Linux下用ls和du命令查看文件以及文件夹大小(转)
  3. crontab每小时运行一次(转)
  4. cortex-m系列的区别(图解)及今日碎片学习笔记
  5. 关于ArrayList
  6. 实现:python3_解析shodan_json数据
  7. MongoDB远程连接-MongoDB Compass
  8. codeblock代码片段
  9. hive基础知识二
  10. Tecplot——为动画添加求解时间(翻译)