文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Springboot编程式事务使用方式详解

2024-12-03 02:02

关注

环境:springboot2.3.9.RELEASE

Spring提供两种编程式事务管理方法:

  1. 使用TransactionTemplate 或 TransactionalOperator
  2. 直接创建TransactionManager的实现

Spring官方推荐使用TransactionTemplate方式

准备

  1. // 实体类 
  2. @Entity 
  3. @Table(name = "BC_USERS"
  4. @Data 
  5. public class Users{ 
  6.     private String username ; 
  7.     private String password ; 
  8.     private Integer status = 0 ; 
  9. // DAO 
  10. public interface UsersRepository extends JpaRepository { 
  11.  
  12.   @Modifying 
  13.   @Query("update Users u set u.status=?1,u.password='123123' where u.id=?2"
  14.   int updateUsers(Integer status, String id) ; 
  15.      
  16. @Mapper 
  17. public interface UsersMapper { 
  18.  
  19.   int insertUser(Users user) ; 
  20.      
  21. // Mapper.xml 
  22. <insert id="insertUser" parameterType="com.pack.domain.Users"
  23.   insert into bc_users (id, username, passwordvalues (#{id}, #{username}, #{password}) 
  24. insert

1 TransactionTemplate

1.1 有返回值的

  1. @Service 
  2. public class UserService { 
  3.      
  4.   @Resource 
  5.   private TransactionTemplate transactionTemplate ; 
  6.   @Resource 
  7.   private UsersRepository usersRepository ; 
  8.      
  9.   public Integer saveUsers(Users users) { 
  10.     this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); 
  11.     Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() { 
  12.       @Override 
  13.       public Integer doInTransaction(TransactionStatus status) { 
  14.         return usersMapper.insertUser(users) ; 
  15.       } 
  16.     }) ; 
  17.     return result ; 
  18.     } 
  19.      

1.2 无返回值的

当没有返回值时可以使用

TransactionCallbackWithoutResult

  1. public void saveUsers(Users users) { 
  2.   transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
  3.     @Override 
  4.     protected void doInTransactionWithoutResult(TransactionStatus status) { 
  5.       usersMapper.insertUser(users) ; 
  6.     } 
  7.   }) ; 

1.3 事务回滚

事务的回滚通过

TransactionStatus.setRollbackOnly方法

  1. public Users saveUser(Users users) { 
  2.   return transactionTemplate.execute(new TransactionCallback() { 
  3.     @Override 
  4.     public Users doInTransaction(TransactionStatus status) { 
  5.       try { 
  6.         return usersMapper.insertUser(users) ; 
  7.       } catch (Exception e) { 
  8.         status.setRollbackOnly() ; 
  9.       } 
  10.       return null ; 
  11.     } 
  12.   }) ; 

1.4 配置事务属性

在实例化TransactionTemplate对象的时候我们可以对事务进行相关的属性配置,通过如下方式。

  1. private TransactionTemplate transactionTemplate ; 
  2.      
  3. public UserService(PlatformTransactionManager transactionManager) { 
  4.   this.transactionTemplate = new TransactionTemplate(transactionManager) ; 
  5.   this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED); 
  6.   this.transactionTemplate.setTimeout(30); //seconds 

测试代码

  1. public Integer updateUsers(Integer statusValue, String id) { 
  2.   return transactionTemplate.execute(new TransactionCallback<Integer>() { 
  3.     @Override 
  4.     public Integer doInTransaction(TransactionStatus status) { 
  5.       return usersRepository.updateUsers(statusValue, id) ; 
  6.     } 
  7.   }) ; 
  8. @Modifying 
  9. @Query("update Users u set u.status=?1 where u.id=?2"
  10. int updateUsers(Integer status, String id) ; 

由于这里事务传播属性设置的NOT_SUPPORTED.所以程序会报错误

  1. org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query 
  2.     at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:403) 
  3.     at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257) 
  4.     at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:531) 

2 TransactionalOperator

TransactionalOperator适用于反应式编程,这里不做介绍。

3 TransactionManager

使用TransactionManager管理事务也有两种

PlatformTransactionManager,

ReactiveTransactionManager

ReactiveTransactionManager适用于反应式编程,这里不做介绍。

3.1 PlatformTransactionManager

在程序中可以使用

PlatformTransactionManager来控制事务的提交与回滚

示例:

  1. private PlatformTransactionManager transactionManager ; 
  2. private DefaultTransactionDefinition definition ; 
  3. private TransactionStatus status ; 
  4. @Resource 
  5. private UsersRepository usersRepository ; 
  6.  
  7. public UserService3(PlatformTransactionManager transactionManager) { 
  8.   this.transactionManager = transactionManager ; 
  9.   definition = new DefaultTransactionDefinition() ; 
  10.   definition.setName("pgName") ; 
  11.   definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED) ; 
  12.      
  13. public Integer saveUsers(Users users) { 
  14.   TransactionStatus status = this.transactionManager.getTransaction(definition) ; 
  15.   Integer result = null ; 
  16.   try { 
  17.     result = usersMapper.insertUser(users) ; 
  18.   } catch (Exception e) { 
  19.     transactionManager.rollback(status) ; 
  20.     throw e ; 
  21.   } 
  22.   transactionManager.commit(status) ; 
  23.   publisher.publishEvent(new UsersEvent(users)); 
  24.   return result ;        

4 事务事件监听

通过@

TransactionalEventListener注解监听事务的不同阶段的事件信息

  1. public @interface TransactionalEventListener { 
  2.   TransactionPhase phase() default TransactionPhase.AFTER_COMMIT; 
  3.   boolean fallbackExecution() default false
  4.   @AliasFor(annotation = EventListener.class, attribute = "classes"
  5.   Class[] value() default {}; 
  6.   @AliasFor(annotation = EventListener.class, attribute = "classes"
  7.   Class[] classes() default {}; 
  8.   String condition() default ""

fallbackExecution: 默认值false;如果设置为true,当前即便没有事务也会触发事件。

TransactionPhase:默认值是事务提交以后;有如下几个取值:

  1. public enum TransactionPhase { 
  2.   BEFORE_COMMIT, // 事务提交前触发 
  3.   AFTER_COMMIT, // 事务提交后触发 
  4.   AFTER_ROLLBACK, // 事务回滚触发 
  5.   AFTER_COMPLETION // 事务完成后 触发 

注意:@

TransactionalEventListener注解只对声明式事务起作用,对编程式事务无效。仅适用于由PlatformTransactionManager管理的线程绑定事务

示例:

  1. // 事件监听 
  2. @Component 
  3. public class TxListenerComponent { 
  4.   @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) 
  5.   public void handleUsersAfterCommit(UsersEvent usersEvent) { 
  6.     Users user = (Users) usersEvent.getSource() ; 
  7.     System.out.println("AfterCommit收到事件通知:" + user.getPassword()) ; 
  8.   } 
  9.   @TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION) 
  10.   public void handleUsersAfterCompletion(UsersEvent usersEvent) { 
  11.     Users user = (Users) usersEvent.getSource() ; 
  12.     System.out.println("AfterCompletion收到事件通知:" + user.getPassword()) ; 
  13.   } 
  14.  
  15.   @TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK) 
  16.   public void handleUsersAfterRollback(UsersEvent usersEvent) { 
  17.     Users user = (Users) usersEvent.getSource() ; 
  18.     System.out.println("AfterRollback收到事件通知:" + user.getPassword()) ; 
  19.   } 
  20.  
  21.   @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT) 
  22.   public void handleUsersBeforeCommit(UsersEvent usersEvent) { 
  23.     Users user = (Users) usersEvent.getSource() ; 
  24.     System.out.println("BeforeCommit收到事件通知:" + user.getPassword()) ; 
  25.   } 
  26. // 发布事件 
  27. @Resource 
  28. private ApplicationEventPublisher publisher ; 
  29. @Resource 
  30. private UsersMapper usersMapper ; 
  31.  
  32. public Integer saveUsers(Users users) { 
  33.   Integer result = transactionTemplate.execute(new TransactionCallback<Integer>() { 
  34.     @Override 
  35.     public Integer doInTransaction(TransactionStatus status) { 
  36.       return usersMapper.insertUser(users) ; 
  37.     } 
  38.   }) ; 
  39.   publisher.publishEvent(new UsersEvent(users)); 
  40.   return result ; 

运行结果:

  1. 2021-06-17 14:02:56.830 DEBUG 10000 --- [nio-8081-exec-1] com.pack.mapper.UsersMapper.insertUser   : ==>  Preparing: insert into bc_users (id, username, password) values (?, ?, ?) 
  2. 2021-06-17 14:02:56.840 DEBUG 10000 --- [nio-8081-exec-1] com.pack.mapper.UsersMapper.insertUser   : ==> Parameters: mmmmm(String), mmmmm(String), mmmmm(String) 
  3. 2021-06-17 14:02:56.842 DEBUG 10000 --- [nio-8081-exec-1] com.pack.mapper.UsersMapper.insertUser   : <==    Updates: 1 
  4. BeforeCommit收到事件通知:mmmmm 
  5. AfterCommit收到事件通知:mmmmm 
  6. AfterCompletion收到事件通知:mmmmm 

总结:编程式的事务适合少量的事务操作;比如在一个服务的调用中有大量的计算操作,最后将计算结果进行事务的操作这种情况就适合应用事务编程式的进行事务控制。如果一个操作有很多的事务的操作那声明式的事务方式就更加的合适。

 

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯