java - 仅当事务通过spring-transactions成功时如何发送电子邮件
问题描述
我想在数据库中创建一个用户,并使用 AWS SES 向这种情况下的用户发送电子邮件。
- 如果用户在数据库中提交事务成功 => 发送电子邮件
- 如果发送电子邮件 AWS SES 失败(检查异常)=> 回滚数据库中的用户创建
- 如果用户在数据库中提交事务失败 => 不要使用 AWS 向用户发送电子邮件
我的代码有问题:如果我的sendEmail
方法抛出异常,则提交事务。
配置:带有 spring-data-jpa 的 Spring-Boot 项目
class EmailServiceImpl {
@Transactional(rollbackFor = Exception.class)
@Override
public User createUserAndSendEmail(UserDto userDto) throws UserEmailException {
try {
//rollback userCreation if sendEmail throw a checkedException
User user = userService.create(userDto);
sendEmail(user);
return user;
} catch (Exception exception) {
throw new UserEmailException(exception.getMessage());
}
}
//don't send email if userCommit in database failed
private void sendEmail(User user) {
amazonEmailService.sendMail(user);
}
}
class UserServiceImpl {
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public User create(UserDto userDto) throws Exception {
User user = mapp(userDto);
return userRepository.save(user);
}
}
解决方案
要在 TX commit 之后执行某些操作,您可以使用@TransactionalEventListener
with TransactionPhase.AFTER_COMMIT
(默认设置)。将您要执行的操作放入TransactionalEventListener
:
使用ApplicationEventPublisher
发布UserCreatedEvent
:
public class EmailServiceImpl {
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Transactional(rollbackFor = Exception.class)
public User createUserAndSendEmail(UserDto userDto) throws UserEmailException {
try {
User user = userService.create(userDto);
//Publish UserCreatedEvent such the UserCreatedEventHandler can handled it after TX commit
applicationContext.publishEvent(new UserCreatedEvent(user));
return user;
} catch (Exception exception) {
throw new UserEmailException(exception.getMessage());
}
}
}
TX 提交后UserCreatedEvent
将由该处理程序处理:
@Component
public class UserCreatedEventHandler {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handle(UserCreatedEvent event) {
try{
amazonEmailService.sendMail(user);
System.out.println("Good, can send email.");
}catch(Exception exception){
System.out.println("Sad, fail to send email , so remove user from DB...");
userService.remove();
}
}
}
Deinum 的好球。如果您使用我的建议,则必须更改userService.create()
为@Transactional(propagation = Propagation.REQUIRES)
推荐阅读
- pandas - 根据数字的长度将数字分成几个部分
- android - 通过静态实例方法发送的参数在片段中丢失
- javascript - 如何显示 d3.js 没有数据消息?
- google-apps-script - GAS 应用程序脚本使用令牌执行 Web 应用程序 - 403 被禁止
- ssl - 如何使用现有证书通过 nodejs 通过 HTTPS 托管
- python - 熊猫:按日期接近过滤
- javascript - 已知设备 ID 的 Web 蓝牙绕过配对屏幕
- google-api - Google Pay API for pass,有什么限制?
- java - 使用 livedata 的 Recyclerview 在数据更改后不更新。只有在我旋转屏幕后
- android - Android模拟器 - 在扩展控件下启用多显示?