java - 仅当使用 spring-transactions 交易成功时如何发送电子邮件

标签 java spring spring-data-jpa 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 后执行某些操作,您可以使用 @TransactionalEventListenerTransactionPhase.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());
            }
        }
    }
    

    UserCreatedEvent TX 提交后将由此处理程序处理:
    @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)

    关于java - 仅当使用 spring-transactions 交易成功时如何发送电子邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54318637/

    相关文章:

    java - JPA 不会将 Id 从包装对象添加到数据库

    java - 我想读取html的内容,我需要用所需的文本更改它

    java - 在 1000 个线程中增加 Java 中的 AtomicInteger 不会生成值 1000

    java - ERROR 411 在 java 中使用 API(POST 方法)

    java - Spring和JSP文件的动态包含

    java - Spring 的 @RequestBody 在 POST 上提供空字符串

    java - pentaho 5.2 中获取 olap4j 连接时出现异常

    spring-data-jpa - 使用 spring 数据搜索嵌套对象,非法尝试取消引用路径源

    java - Spring Boot JPA 元模型不能为空!当尝试运行 JUnit/集成测试时

    java - JpaRepository中通过自定义SQL排序方法排序