【问题标题】:JMS and JPA - transactional services best practicesJMS 和 JPA - 事务服务最佳实践
【发布时间】:2014-01-23 11:49:06
【问题描述】:

我们正在使用带有 jpa 和 jms 的 spring 框架。

我们的大部分服务都涉及 DB 持久性和 JMS 消息抛出。

这是一个例子:

@Override
@Transactional
public void createAccount(PlayerDTO playerDTO) {

    Player newPlayer  = new Player(playerDTO);

    playerRepository.save(newPlayer);

    produceJmsMessage(new PlayerCreatedEvent());
 }

问题是,jms 不是我们事务处理的一部分。 (仅 jpaTransactionManager) 因此,每当执行最后一行时,都会触发消息,而不会发生对 DB 的提交。

现在想象一下,其中一个消息消费者正试图获取播放器以处理某些内容,但是!当他从数据库中获取玩家时,它还没有被提交!

在各种各样的情况下,这种情况一直发生在我们身上。

现在,我们当然可以使用 JTA,但性能影响是无法承受的,而且它在文档和其他方面似乎真的不受欢迎,

所以问题是:

开发人员如何缓解我们在此处描述的这个问题? (没有 JPA)。

最好的,

【问题讨论】:

  • 在我们的应用程序(Java EE 5,而不是 Spring)中,我们使用 XA Transactions,它工作正常。

标签: java spring jms jta transactional


【解决方案1】:

sessionTransacted 属性解决了我的问题,它实际上是等到事务提交后再触发事件。 (默认设置为OFF):

<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory" ref="cachingConnectionFactory" />
    <property name="messageConverter" ref="eventConverter" />
    <property name="sessionTransacted" value="true"/>
</bean>

【讨论】:

  • 节省了我的时间..非常感谢 :)
【解决方案2】:

您可以用外观包装您的事务性PlayerService - 或任何负责拯救玩家的东西 - 。 PlayerService 可能只负责以事务方式保存玩家 - 而外观可能负责调用 PlayerService 然后生成消息。从PlayerService 中分离发送操作将确保Player 在生成消息之前被提交。例如:

@Service
public class PlayerServiceImpl implements PlayerService {

    @Autowired
    private PlayerRepository playerRespository;

    @Override
    @Transactional
    public void savePlayer(PlayerDTO playerDTO) {
        Player newPlayer  = new Player(playerDTO);

        // Responsible for saving the player only
        playerRepository.save(newPlayer);
    }

    ...
}

然后可以用某种外观包裹它。

@Service
public class PlayerFacade {

    @Autowired
    private PlayerService playerService;

    public void createAccount(PlayerDTO playerDTO) {
        playerService.savePlayer(playerDTO);

        // Generate the message after successful save.
        // The player would be committed at this point because
        // the savePlayer method (and thus transaction) has completed
        produceJmsMessage(new PlayerCreatedEvent());
    }
}

然后,客户端代码将直接与 PlayerFacade 而不是 PlayerService 交互 - 以确保播放器被保存并发送消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-12
    • 2014-07-07
    • 2011-12-16
    • 1970-01-01
    • 2018-09-25
    • 2015-07-26
    • 1970-01-01
    • 2021-01-17
    相关资源
    最近更新 更多