对springBoot事务的一些初步了解
对springBoot事务的一些初步了解
springboot事务初步了解
什么是事务:
事务由单独单元的一个或者多个sql语句组成,在这个单元中,每个sql语句时相互依赖的。而整个单独单元作为一个不可分割的整体,如果单元中某条sql语句一旦执行失败或者产生错误,整个单元将会回滚,也就是所有受到影响的数据将会返回到事务开始以前的状态;如果单元中的所有sql语句均执行成功,则事务被顺利执行
事务的属性:
- 原子性:一个事务不可在分割,要么都执行要么都不执行。
- 一致性:一个事务的执行会使数据从一个一致状态切换到另一个一致的状态。
- 隔离性:一个事务的执行不受其他事物的干扰
- 持久性: 一个事务一旦提交,则会永久的改变数据库的数据
事务的两种管理方式
注解式事务管理
在SpringBoot中声明式事务最常见,就是把需要事务的方法用@Transactional标注一下就行了,这个一般用在Service层。标注后该方法就具备了事务的能力,出错了会自动回滚。
在大部分场景下,该方法已经够用了。
- 在入口类使用注解
@EnableTransactionManagement
开启事务 - 在访问数据库的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。
业务中相关的应用
业务场景
在项目中,往往需要执行数据库操作后,发送消息或事件来异步调用其他组件执行相应的操作,例如:
用户注册后发送激活码;
配置修改后发送更新事件等。
但是,数据库的操作如果还未完成,此时异步调用的方法查询数据库发现没有数据,这就会出现问题
解决方案
- 使用注解
@TransactionalEventListener
- 使用
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),我们将第一时间核实后及时予以删除。