同步Hibernate持久性+ Spring AMQP发布事务



在我的应用程序中,用户创建了一个帖子,该帖子被持久化在数据库中,并发布到Spring amqp队列

当用户创建post flow到达控制器时

@RequestMapping(value="/createPost", method=RequestMethod.POST, consumes = "application/json", 
            produces = "application/json")
    public @ResponseBody Post createUserPost(@RequestBody(required=false) Post post, Principal principal){
        this.userService.persistPost(post);
        logger.info("post persistance successful");
        publishService.publishUserPosts(post);
        return post;
    }

有两个服务persistPost &控制器中调用的不同服务类中的publishUserPosts

Publish Service

@Transactional
    public void publishUserPosts(Post post){
        try{
            logger.info("Sending user post to the subscribers");
            amqpTemplate.convertAndSend(post);
            }catch(AmqpException e){
                throw new MyAppException(e);
            }
    }

问题是两个服务调用在不同的事务下运行。如果PublishPost事务失败,该post仍然在db中持久化。

为了将两个服务置于一个事务中,我更改了代码&在PublishPost类中注入persistPost服务

@Transactional
    public void publishUserPosts(Post post){
        try{
            userService.persistPost(post);
            logger.info("post persistance successful");
            logger.info("Sending user post to the subscribers");
            amqpTemplate.convertAndSend(post);
            }catch(AmqpException e){
                throw new MyAppException(e);
            }
    }

我的问题

这是在单个事务下实现多个服务的最佳方法吗?还是我可以用其他方法做得更好?

我想你对事务的工作方式感到困惑。HiberanteTransactionManager只能处理数据库操作。要使其他部分也具有事务性,例如消息传递,您必须使用称为Java事务性API (JTA)的技术,该技术允许将不同技术的事务合并为一个大的分布式事务。在Spring中,这是由JTATransactionManage提供的。

无论上述情况如何,在这种情况下(如果您遵循领域驱动的设计模式),更被接受的设计是使用一个应用程序服务,它充当您的领域的facade,并负责保持事务边界。这个应用程序服务然后调用Post Repository(您称之为userService)并最终发布消息。在伪代码

class PostApplicationService {
   @Transactional
   public void publishUserPosts(Post post){
      postRepository.save(post);
      publishService.notifyNewPost(post);
   }
}

我将使用本地事件总线(如Spring或Guava提供的总线)执行通知。但这只是我的偏好:)

最新更新