当前位置: 首页 >Java技术 > 对springBoot事务的一些初步了解

对springBoot事务的一些初步了解

对springBoot事务的一些初步了解


springboot事务初步了解

什么是事务:

事务由单独单元的一个或者多个sql语句组成,在这个单元中,每个sql语句时相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元中某条sql语句一旦执行失败或者产生错误,整个单元将会回滚,也就是所有受到影响的数据将会返回到事务开始以前的状态;如果单元中的所有sql语句均执行成功,则事务被顺利执行

事务的属性:

  • 原子性:一个事务不可在分割,要么都执行要么都不执行。
  • 一致性:一个事务的执行会使数据从一个一致状态切换到另一个一致的状态。
  • 隔离性:一个事务的执行不受其他事物的干扰
  • 持久性: 一个事务一旦提交,则会永久的改变数据库的数据

事务的两种管理方式

注解式事务管理

在SpringBoot中声明式事务最常见,就是把需要事务的方法用@Transactional标注一下就行了,这个一般用在Service层。标注后该方法就具备了事务的能力,出错了会自动回滚。
在大部分场景下,该方法已经够用了。

  1. 在入口类使用注解@EnableTransactionManagement开启事务
  2. 在访问数据库的service方法上添加注解@Transactional即可
@SpringBootApplication@EnableTransactionManagementpublic class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}}
@Servicepublic class TestServiceImpl implements TestService {@Autowiredprivate UserMapper userMapper;@Override@Transactionalpublic void updataUser(int id,String name) {//sql相关接口实现}}

编程式事务管理

在有些场景下,我们需要获取事务的状态,是执行成功了还是失败回滚了,那么使用声明式事务就不够用了,需要编程式事务。
在SpringBoot中,可以使用两种编程式事务。

  • TransactionTemplate
@Servicepublic class TestServiceImpl implements TestService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate TransactionTemplate transactionTemplate;@Overridepublic void updataUser(int id,String name) {User user = new User();user.setName(name);user.setId(id);transactionTemplate.execute(new TransactionCallback<Object>() {@Overridepublic Object doInTransaction(TransactionStatus transactionStatus) {try {//在doIntransaction里做逻辑处理即可boolean res = userMapper.updateUser(user);}catch (Exception e){//如果出异常了,就执行isRollbackOnly方法进行回滚transactionStatus.isRollbackOnly();e.printStackTrace();}retu null;}});}}
  • TransactionManager
@Servicepublic class TestServiceImpl implements TestService {@Autowiredprivate UserMapper userMapper;@Autowiredprivate PlatformTransactionManager transactionManager;@Overridepublic void updataUser(int id,String name) {User user = new User();user.setName(name);user.setId(id);TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());try{//进行sql逻辑处理boolean res = userMapper.updateUser(user);transactionManager.commit(status);}catch (Exception e){transactionManager.rollback(status);e.printStackTrace();}}}

使用这个就可以把事务结果同步返回给调用端了,出异常了就返回false,成功了就true。


业务中相关的应用

业务场景

在项目中,往往需要执行数据库操作后,发送消息或事件来异步调用其他组件执行相应的操作,例如:
用户注册后发送激活码;
配置修改后发送更新事件等。
但是,数据库的操作如果还未完成,此时异步调用的方法查询数据库发现没有数据,这就会出现问题

解决方案

  1. 使用注解@TransactionalEventListener
  2. 使用TransactionSynchronizationManager方法
  • TransactionalEventListener
@Servicepublic class TransactionEventTestService {@Resourceprivate TestMapper mapper;@Resourceprivate ApplicationEventPublisher publisher;@Transactionalpublic void addTestModel() {TestModel model = new TestModel();model.setName("haogrgr");mapper.insert(model);//对于@TransactionalEventListener, 会在事务提交后才执行Listener处理逻辑.//发布事件, 事务提交后, 记录日志, 或发送消息等操作publisher.publishEvent(model);}//当事务提交后, 才会真正的执行@TransactionalEventListener配置的Listener, 如果Listener抛异常, 方法返回失败, 但事务不会回滚.}@Componentpublic class TransactionEventListener {@TransactionalEventListenerpublic void handle(PayloadApplicationEvent<TestModel> event) {System.out.println(event.getPayload().getName());//这里可以记录日志, 发送消息等操作.//这里抛出异常, 会导致addTestModel方法异常, 但不会回滚事务.}}
  • TransactionSynchronizationManager
//线程池异步调用提高性能private final ExecutorService executorService = Executors.newFixedThreadPool(5);public void insert(TechBook techBook){bookMapper.insert(techBook); //send after tx commit but is asyncTransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {@Overridepublic void afterCommit() {executorService.submit(new Runnable() {@Overridepublic void run() {System.out.println("send email after transaction commit...");try {Thread.sleep(10*1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("complete send email after transaction commit...");}});}}); //async work but tx not work, execute even when tx is rollback//asyncService.executeAfterTxComplete(); ThreadLocalRandom random = ThreadLocalRandom.current();if(random.nextInt() % 2 ==0){throw new RuntimeException("test email transaction");}System.out.println("service end");}

作者:lgbisha
来源链接:https://blog.csdn.net/lgbisha/article/details/100519051

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/java/117219.html

分享给朋友:

“对springBoot事务的一些初步了解” 的相关文章

Linux使用yum命令安装jdk1.8 2022年05月15日 09:16:48
yum安装步骤(网络下载安装) 2022年05月15日 10:23:29
SpringBoot之整合Mybatis篇 2022年05月15日 21:51:04
数组转LIst的几种方法 2022年05月16日 11:18:24
网络协议栈基本知识 2022年05月16日 20:33:52
java中将英尺换算为身高 2022年05月21日 11:37:21
Java对象的大小 2022年05月21日 11:41:30