【问题标题】:EJB Container Managed Transaction with JDBC Result Set and MDB带有 JDBC 结果集和 MDB 的 EJB 容器托管事务
【发布时间】:2016-02-26 14:17:12
【问题描述】:

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

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 中,我想从表“用户”中获取所有用户,包括最后插入的用户(当循环仍在迭代列表时,可能尚未提交)。获取过程发生在另一个由 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. 是否有其他方法可以做到这一点?

【问题讨论】:

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


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

    【讨论】:

    • "如果你从注入的 EntityManager 中解开它"。这是什么意思?
    • 就我而言,我只是使用 InitialContext 查找数据源 JNDI。如果我在 onMessage 方法中创建一个新事务(使用 UserTransaction.begin())怎么办?前一个事务(发生在第一个 EJB 中)会被提交吗?
    • 我不确定直接管理的 JDNI 连接的行为是什么。我在回答中描述的是从EntityManager 解包时。
    • @Bogie 你成功了吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    • 2015-11-26
    • 2020-07-23
    • 2013-10-07
    相关资源
    最近更新 更多