同步 Hibernate 持久性 + Spring AMQP 发布事务
Synchronizing Hibernate persistence + Spring AMQP publish transactions
在我的应用程序中,用户创建了一个 post,它持久保存在数据库中 + 发布到 Spring amqp 队列
当用户创建一个 post 流点击控制器时
@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
在控制器中调用的不同服务 classes 中。
发布服务
@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 仍然保留在数据库中。
为了将这两项服务置于单个事务下,我更改了代码并在 PublishPost
class.
中注入了 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 提供的。
尽管如此,在这种情况下(如果您遵循领域驱动设计模式)更可接受的设计是拥有一个 Application Service which acts as a facade to your domain and is responsible for keeping the transactional boundary. This Application Service then calls the Post Repository(您所谓的 userService
)并最终发布信息。所以在伪代码中
class PostApplicationService {
@Transactional
public void publishUserPosts(Post post){
postRepository.save(post);
publishService.notifyNewPost(post);
}
}
我会使用本地事件总线(例如 Spring 或 Guava 提供的事件总线)进行通知。但这只是我的偏好:).
在我的应用程序中,用户创建了一个 post,它持久保存在数据库中 + 发布到 Spring amqp 队列
当用户创建一个 post 流点击控制器时
@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
在控制器中调用的不同服务 classes 中。
发布服务
@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 仍然保留在数据库中。
为了将这两项服务置于单个事务下,我更改了代码并在 PublishPost
class.
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 提供的。
尽管如此,在这种情况下(如果您遵循领域驱动设计模式)更可接受的设计是拥有一个 Application Service which acts as a facade to your domain and is responsible for keeping the transactional boundary. This Application Service then calls the Post Repository(您所谓的 userService
)并最终发布信息。所以在伪代码中
class PostApplicationService {
@Transactional
public void publishUserPosts(Post post){
postRepository.save(post);
publishService.notifyNewPost(post);
}
}
我会使用本地事件总线(例如 Spring 或 Guava 提供的事件总线)进行通知。但这只是我的偏好:).