Springboot编程式事务使⽤⽅式详解环境:springboot2.3.9.RELEASE
Spring提供两种编程式事务管理⽅法:
1. 使⽤TransactionTemplate 或 TransactionalOperator
2. 直接创建TransactionManager的实现
Spring官⽅推荐使⽤TransactionTemplate⽅式
准备
// 实体类
@Entity
@Table(name = "BC_USERS")
@Data
public class Users{
private String username ;
private String password ;
private Integer status = 0 ;
}
// DAO
public interface UsersRepository extends JpaRepository<Users, String> {
@Modifying
@Query("update Users u set u.status=?1,u.password='123123' where u.id=?2")
int updateUsers(Integer status, String id) ;
}
@Mapper
public interface UsersMapper {
int insertUser(Users user) ;
}
// l
<insert id="insertUser" parameterType="com.pack.domain.Users">
insert into bc_users (id, username, password) values (#{id}, #{username}, #{password})
</insert>
1 TransactionTemplate
1.1 有返回值的
@Service
public class UserService {
@Resource
private TransactionTemplate transactionTemplate ;
@Resource
private UsersRepository usersRepository ;
public Integer saveUsers(Users users) {
Integer result = ute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
return usersMapper.insertUser(users) ;
}
}) ;
return result ;
}
}
1.2 ⽆返回值的
当没有返回值时可以使⽤
TransactionCallbackWithoutResult
public void saveUsers(Users users) {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
usersMapper.insertUser(users) ;
}
}) ;
}
1.3 事务回滚
事务的回滚通过
TransactionStatus.setRollbackOnly⽅法
public Users saveUser(Users users) {
ute(new TransactionCallback<Users>() {
@Override
public Users doInTransaction(TransactionStatus status) {
try {
return usersMapper.insertUser(users) ;
} catch (Exception e) {
status.setRollbackOnly() ;
}
return null ;
}
}) ;
}
1.4 配置事务属性
在实例化TransactionTemplate对象的时候我们可以对事务进⾏相关的属性配置,通过如下⽅式。
private TransactionTemplate transactionTemplate ;
public UserService(PlatformTransactionManager transactionManager) {
}
测试代码
public Integer updateUsers(Integer statusValue, String id) {
ute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
return usersRepository.updateUsers(statusValue, id) ;
}
}) ;
}
@Modifying
@Query("update Users u set u.status=?1 where u.id=?2")
int updateUsers(Integer status, String id) ;
由于这⾥事务传播属性设置的NOT_SUPPORTED.所以程序会报错误
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query at vertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:403)
at jpa.anslateExceptionIfPossible(HibernateJpaDialect.java:257)
at anslateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:531)
2 TransactionalOperator
TransactionalOperator适⽤于反应式编程,这⾥不做介绍。
3 TransactionManager
使⽤TransactionManager管理事务也有两种
PlatformTransactionManager,
ReactiveTransactionManager
ReactiveTransactionManager适⽤于反应式编程,这⾥不做介绍。
3.1 PlatformTransactionManager
在程序中可以使⽤
PlatformTransactionManager来控制事务的提交与回滚
⽰例:
private PlatformTransactionManager transactionManager ;
private DefaultTransactionDefinition definition ;
private TransactionStatus status ;
@Resource
private UsersRepository usersRepository ;
public UserService3(PlatformTransactionManager transactionManager) {
definition = new DefaultTransactionDefinition() ;
definition.setName("pgName") ;
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED) ;
}
public Integer saveUsers(Users users) {
TransactionStatus status = Transaction(definition) ;
Integer result = null ;
try {
result = usersMapper.insertUser(users) ;
} catch (Exception e) {
throw e ;
}
transactionManagermit(status) ;
publisher.publishEvent(new UsersEvent(users));
return result ;
}
4 事务事件监听
通过@
TransactionalEventListener注解监听事务的不同阶段的事件信息
public @interface TransactionalEventListener {
TransactionPhase phase() default TransactionPhase.AFTER_COMMIT;
boolean fallbackExecution() default false;
@AliasFor(annotation = EventListener.class, attribute = "classes")
Class<?>[] value() default {};
@AliasFor(annotation = EventListener.class, attribute = "classes")
Class<?>[] classes() default {};
String condition() default "";
}
fallbackExecution: 默认值false;如果设置为true,当前即便没有事务也会触发事件。
TransactionPhase:默认值是事务提交以后;有如下⼏个取值:
public enum TransactionPhase {
BEFORE_COMMIT, // 事务提交前触发
AFTER_COMMIT, // 事务提交后触发
AFTER_ROLLBACK, // 事务回滚触发
AFTER_COMPLETION // 事务完成后触发
}
注意:@
TransactionalEventListener注解只对声明式事务起作⽤,对编程式事务⽆效。仅适⽤于由PlatformTransactionManager管理的线程绑定事务
⽰例:
// 事件监听
@Component
public class TxListenerComponent {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleUsersAfterCommit(UsersEvent usersEvent) {
Users user = (Users) Source() ;
System.out.println("AfterCommit收到事件通知:" + Password()) ;
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMPLETION)
public void handleUsersAfterCompletion(UsersEvent usersEvent) {
Users user = (Users) Source() ;
System.out.println("AfterCompletion收到事件通知:" + Password()) ;
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleUsersAfterRollback(UsersEvent usersEvent) {
Users user = (Users) Source() ;
System.out.println("AfterRollback收到事件通知:" + Password()) ;
}
@TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
public void handleUsersBeforeCommit(UsersEvent usersEvent) {
Users user = (Users) Source() ;
System.out.println("BeforeCommit收到事件通知:" + Password()) ;
}
}
// 发布事件
@Resource
private ApplicationEventPublisher publisher ;
@Resource
private UsersMapper usersMapper ;
public Integer saveUsers(Users users) {
Integer result = ute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
return usersMapper.insertUser(users) ;
}
}) ;
publisher.publishEvent(new UsersEvent(users));
return result ;
}
运⾏结果:
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 (?, ?, ?)
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)
2021-06-17 14:02:56.842 DEBUG 10000 --- [nio-8081-exec-1] com.pack.mapper.UsersMapper.insertUser : <== Updates: 1
BeforeCommit收到事件通知:mmmmm
AfterCommit收到事件通知:mmmmmspring framework表达式assign
AfterCompletion收到事件通知:mmmmm
总结:编程式的事务适合少量的事务操作;⽐如在⼀个服务的调⽤中有⼤量的计算操作,最后将计算结果进⾏事务的操作这种情况就适合应⽤事务编程式的进⾏事务控制。如果⼀个操作有很多的事务的操作那声明式的事务⽅式就更加的合适。
完毕!!!
给个关注+转发吧谢谢
公众:Springboot实战案例锦集
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论