Atomikos + Spring + JMS以事务方式批量读取消息

时间:2013-02-14 16:22:59

标签: spring transactions jms jta atomikos

我正在尝试使用spring + atomikos设计一个应用程序,该应用程序读取一批N条消息并将它们持久保存到单个事务中的数据库中。它必须是一批消息,因为数据在批量生成时才是一致的,即单个消息不足以进行一致的事务。此外,每条消息有一个交易绝对会影响我的表现。这不是典型的JMS + DB应用程序,因此我很难在线查找示例(我尝试使用在atomikos网站上建议的MessageListener,但每个消息创建一个事务)。使用Spring实现这一目标的最佳方法是什么? 感谢

乔瓦尼

2 个答案:

答案 0 :(得分:0)

我认为您的问题与Spring或Atomikos无关。这更像是一个设计问题。

如果您需要在单个事务中提交所有消息,请在将完整消息发送到持久层之前将它们全部合并到更大的结构中。

答案 1 :(得分:0)

弄清楚我需要做什么。在我的spring配置文件中,我需要配置以下内容:

  • org.springframework.transaction.jta.JtaTransactionManager类的实例(例如配置为使用atomikos),其中注入了“transactionManager”和“userTransaction”依赖项,例如,类com.atomikos.icatch.jta.UserTransactionManagercom.atomikos.icatch.jta.UserTransactionImp的实例;
  • <tx:annotation-driven transaction-manager="txManager">标记在客户端代码中使用注释驱动的事务;
  • 向事务管理器注册JMS连接工厂,例如,通过创建com.atomikos.jms.AtomikosConnectionFactoryBean的实例;
  • 队列对象,例如com.tibco.tibjms.TibjmsQueue或类似的实例;
  • JmsTemplate,其依赖项“defaultDestination”注入先前创建的队列;
  • 向事务管理器注册数据库,例如,为最后一个资源开局场景创建com.atomikos.jdbc.AtomikosDataSourceBean(或com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean的实例);
  • 一个或多个SqlUpdate(或BatchSqlUpdate或JdbcTemplate)实例(每个数据源一个),每个实例都注入了先前定义的数据源的“dataSource”属性;
  • 自定义DAO类的一个实例,它注入了先前定义的JmsTemplate和SqlUpdate对象:此类将有一个或多个带注释的@Transactional方法,它们将使用JmsTemplate执行事务以接收消息和SqlUpdate (s)将它们保留在数据库中,例如,它可能是一个类似于这样的类:

    public class MyDao{        
      JmsTemplate jmsTemplate; // getter/setter omitted for clarity
      BatchSqlUpdate sqlUpdate; // getter/setter omitted for clarity
    
      @Transactional
      public void persistMessages(int n){
        // map used for the sqlUpdate object
        Map<String, Object> params = new HashMap<>();
        // need to reset this since it's being reused
        sqlUpdate.reset();
        for(int i=0;i<n;i++){
          // retrieve a message synchronously
          Message msg = jmsTemplate.receive();
          // transform the message
          doSomeMagic(msg,params);
          // set parameters in the SQL
          sqlUpdate.updateByNamedParam(params);
        }
        // now the batch can be flushed
        sqlUpdate.flush();
      }
    
      private void doSomeMagic(Message msg, Map<String,Object> params){
        // implementation is application-dependent!
        // the only assumption is that somehow the
        // message can be used to set the named
        // parameters in the sqlUpdate object
      }
    }
    

唯一值得注意的是DAO 必须是弹簧管理的,因为使用注释需要spring来创建代理。