2014-01-23 54 views
1

我們使用jpa和jms的spring框架。JMS和JPA--交易服務最佳實踐

我們的大部分服務都涉及數據庫持久性和JMS消息投擲。

下面是一個例子:

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

    Player newPlayer = new Player(playerDTO); 

    playerRepository.save(newPlayer); 

    produceJmsMessage(new PlayerCreatedEvent()); 
} 

問題是,JMS是不是我們交易過程的一部分。 (只有jpaTransactionManager) ,因此每當最後一行執行消息時觸發數據庫而不提交數據庫。

現在想象一下消息消費者正試圖獲取玩家以便處理一些東西,但!當他從數據庫中提取玩家時,它還沒有被提交!

這種情況在各種場景中都發生在我們身上。現在

的,當然,我們可以使用JTA,但對性能的影響是無法忍受的,而且它似乎是關於文檔和東西實在不得人心,

所以,問題是:

怎麼辦開發人員緩解我們在這裏描述的這個問題? (沒有JPA)。

最佳,

+0

在我們的應用程序(Java EE 5,而不是Spring)中,我們使用XA事務並且工作正常。 – Puce

回答

3

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> 
+0

保存我的時間..謝謝一噸:) – Swamy

1

你可以換你的交易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直接互動 - 以確保雙方的球員被保存和發送消息。