具有JDBC结果集和MDB的EJB容器管理事务

时间:2015-11-24 08:22:43

标签: java jdbc ejb jms message-driven-bean

我有一个无状态会话bean。在下面的方法中,我循环列表以将每个用户插入表'user'。

void saveUserList(List<User> users) {
  try {
    conn = dataSource.getConnection();
    PreparedStatement ps;

    try {
      ps = conn.prepareStatement(INSERT_USER_LIST);

      for (User user : users) {
        ps.setString(1, user.getName);

        if (ps.executeUpdate() > 0) {
          sendJMSMessage();
        }
      }
    }
  } catch (SQLException e) {
    // catch error!!
  } finally {
    closeResource(conn);
  }
}

每次成功插入后,触发标志将发送到MDB。这是sendJMSMessage方法......

void sendJMSMessage() {
  conn = connectionFactory.createQueueConnection();
  qsession = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
  QueueSender sender = qsession.createSender(queue);
  conn.start();

  TextMessage flag = qsession.createTextMessage("triggerFlag");
  flag.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT);
  sender.send(flag);
}

然后它将调用MDB的onMessage方法。这里,在onMessage中,我想从表'user'中获取所有用户,包括最后插入的用户(当循环仍在迭代列表时可能尚未提交)。获取过程发生在由onMessage调用的另一个无状态EJB中。我预计记录会在那里获取。但结果集一无所获。

void onMessage(Message message) {
  TextMessage obj = (TextMessage) message;

  if (obj.getText.equals("triggerFlag")) {
    ArrayList<User> users = someBean.getUsers();
    // Do something with them, as well as the new user.
  }
}

使用当前代码,我通常需要通过传递不同的列表来重新执行saveUserList()以获得预期的结果。我想知道的是:

  1. 有可能吗?
  2. 第一个插入事务何时被提交?
  3. MDB可以读取表中未提交的更改吗?
  4. 从EJB触发的MDB中读取表更改的正确方法是什么?
  5. 有替代方法吗?

1 个答案:

答案 0 :(得分:1)

  1. 是的,有可能。
  2. 这实际上取决于你如何获得连接(或DataSource)。如果从注入的EntityManager中解包它,那么当您(首次输入的)EJB方法返回时,事务会自动提交(默认情况下是这样,即如果没有其他注释的话!)
  3. 是的,如果MDB的连接使用最低的事务隔离级别&#34; READ_UNCOMMITTED&#34;。这不是一件容易实现的事情,而是取决于你如何获得连接。
  4. (&amp; 5)解决问题的最简洁方法可能是手动控制事务(使用注入的UserTransaction,而不是容器管理事务(CMT))。只有你完成了整个用户列表(不是你现在所做的每个用户)和你提交事务后(用UserTransaction编程),你是100%,你的第二个无状态bean会看到你所有的用户。在这种情况下,您应该只发送一次消息。