当前位置: 首页 > 科技观察

Springboot编程式事务使用详解

时间:2023-03-13 21:47:48 科技观察

环境:springboot2.3.9.RELEASESSpring提供了两种编程式事务管理方式:使用TransactionTemplate或TransactionalOperator直接创建TransactionManager的实现Spring官方推荐使用TransactionTemplate编写//实体类@Entity@Table(name="BC_USERS")@DatapublicclassUsers{privateStringusername;privateStringpassword;privateIntegerstatus=0;}//DAOpublicinterfaceUsersRepositoryextendsJpaRepository{@Modifying@Query("updateUsersusetu.status=?1,u.password='123123'whereu.id=?2")intupdateUsers(Integerstatus,Stringid);}@MapperpublicinterfaceUsersMapper{intinsertUser(Usersuser);}//Mapper.xmlinsertintobc_users(id,username,password)values(#{id},#{username},#{password})1TransactionTemplate1.1@ServicepublicclassUserService{@ResourceprivateTransactionTemplatetransactionTem盘子;@ResourceprivateUsersRepositoryusersRepository;publicIntegersaveUsers(我们ersusers){this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);Integerresult=transactionTemplate.execute(newTransactionCallback(){@OverridepublicIntegerdoInTransaction(TransactionStatusstatus){returnusersMapper.insertUser(用户);}resuser(用户);}nres2);当没有返回值时,可以使用TransactionCallbackWithoutResultpublicvoidsaveUsers(Usersusers){transactionTemplate.execute(newTransactionCallbackWithoutResult(){@OverrideprotectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){usersMapper.insertUser(users);}});}1.3事务回滚事务回滚传递TransactionStatus.setRollbackOnly方法publicUserssaveUser(Usersusers){returntransactionTemplate.execute(newTransactionCallback(){@OverridepublicUsersdoInTransaction(TransactionStatusstatus){try{returnusersMapper.insertUser(users);}catch(Exceptione){status.setRollbackOnlynn();}}});}1.4配置交易属性在实例化TransactionTemplate对象时,我们可以通过以下方法配置交易相关的属性privateTransactionTemplatetransactionTemplate;publicUserService(PlatformTransactionManagertransactionManager){this.transactionTemplate=newTransactionTemplate(transactionManager);this.transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);this.transactionTemplate.setTimeout(30);//秒}测试代码publicIntegerupdateUsers(Integerstatlate)usValue,turntransactionidlate)usValue.execute(newTransactionCallback(){@OverridepublicIntegerdoInTransaction(TransactionStatusstatus){returnusersRepository.updateUsers(statusValue,id);}});}@Modifying@Query("updateUsersusetu.status=?1whereu.id=?2")intupdateUsers(Integerstatus,Stringid);由于这里事务传播属性设置的NOT_SUPPORTED.所以程序会报错误org.springframework.dao.InvalidDataAccessApiUsageException:Executinganupdate/deletequery;nestedexceptionisjavax.persistence.TransactionRequiredException:Executinganupdate/deletequeryatorg.springframework.orm.jpa.EntityManagerFactoryUtils.传达rtJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:403)atorg.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:257)atorg.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:531)2TransactionalOperatorTransactionalOperator适用于响应式编程,这里不介绍3TransactionManager使用TransactionManager管理事务还有两个PlatformTransactionManager,ReactiveTransactionManagerReactiveTransactionManager适用于响应式编程,这里不再介绍。3.1PlatformTransactionManager在程序中可以使用PlatformTransactionManager来控制事务的提交与回滚示例:privatePlatformTransactionManagertransactionManager;privateDefaultTransactionDefinitiondefinition;privateTransactionStatusstatus;@ResourceprivateUsersRepositoryusersRepository;publicUserService3(PlatformTransactionManagertransactionManager){this.transactionManager=transactionManager;definition=newDefaultTransactionDefinition();definition.setName("pgName");definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);}publicIntegersaveUsers(Usersusers){TransactionStatusstatus=this.transactionManager.getTransaction(definition);Integerresult=null;try{result=usersMapper.insertUser(users);}catch(Exceptione){transactionManager.rollback(status);throwe;}transactionManager.commit(status);publisher.publishEvent(newUsersEvent(users));returnresult;}4事务事件监听通过@TransactionalEventListener注解监听事务不同阶段的事件信息酒吧lic@interfaceTransactionalEventListener{事务Phasephase()defaultTransactionPhase.AFTER_COMMIT;booleanfallbackExecution()defaultfalse;@AliasFor(annotation=EventListener.class,attribute="classes")Class[]value()default{};@AliasFor(annotation=EventListener.class,attribute)="classes")Class[]classes()default{};Stringcondition()default"";}fallbackExecution:默认值为false;如果设置为true,即使当前没有事务也会触发该事件TransactionPhase:默认值为事务提交后;有以下值:publicenumTransactionPhase{BEFORE_COMMIT,//事务提交前触发AFTER_COMMIT,//事务提交后触发AFTER_ROLLBACK,//事务回滚触发AF??TER_COMPLETION//事务完成后触发}注意:@TransactionalEventListener注解仅适用于声明式事务,不适用于程序化交易。仅适用于PlatformTransactionManager示例管理的线程绑定事务://EventListener@ComponentpublicclassTxListenerComponent{@TransactionalEventListener(phase=TransactionPhase.AFTER_COMMIT)publicvoidhandleUsersAfterCommit(UsersEventusersEvent){Usersuser=(Users)usersEvent.getSource();System.out.println("AfterCommit收到事件通知:"+user.getPassword());}@TransactionalEventListener(phase=TransactionPhase.AFTER_COMPLETION)publicvoidhandleUsersAfterCompletion(UsersEventusersEvent){Usersuser=(Users)usersEvent.getSource();System.out.println("AfterCompletion收到事件通知:“+user.getPassword());}@TransactionalEventListener(phase=TransactionPhase.AFTER_ROLLBACK)publicvoidhandleUsersAfterRollback(UsersEventusersEvent){Usersuser=(Users)usersEvent.getSource();System.out.println("AfterRollbackTo事件通知:“+user.getPassword());}@TransactionalEventListener(phase=TransactionPhase.BEFORE_COMMIT)publicvoidhandleUsersBeforeCommit(UsersEventusersEvent){Usersuser=(用户)usersEvent.getSource();Ssystem.out.println("BeforeCommit收到事件通知:"+user.getPassword());}}//发布事件@ResourceprivateApplicationEventPublisherpublisher;@ResourceprivateUsersMapperusersMapper;publicIntegersaveUsers(Usersusers){Integerresult=transactionTemplate.execute(newTransactionCallback(){@OverridepublicIntegerdoInTransaction(TransactionStatusstatus){returnusersMapper.insertUser(users);}});publisher.publishEvent(newUsersEvent(users));returnresult;}运行结果:2021-06-1714:02:56.830DEBUG10000---[nio-8081-exec-1]com.pack.mapper.UsersMapper.insertUser:==>Preparing:insertintobc_users(id,username,password)values(?,?,?)2021-06-1714:02:56.840DEBUG10000---[nio-8081-exec-1]com.pack.mapper.UsersMapper.insertUser:==>参数:mmmmm(String),mmmmm(String),mmmmm(String)2021-06-1714:02:56.842DEBUG10000---[nio-8081-exec-1]com.pack.mapper.UsersMapper.insertUser:<==Updates:1BeforeCommit收到事件通知:mmmmAfterCommit收到事件通知:mmmmmAfterCompletion收到的事件通知:mmmmm总结:programmaticTransactions适用于少量事务操作;比如一个服务调用中有大量的计算操作,计算结果最终用于事务操作。这种情况适用于事务控制的应用程序事务编程。如果一个操作有很多事务操作,声明式事务方式比较合适。更加合适。