【问题标题】:WildFly not persisting stored procedure call in MySQLWildFly 不在 MySQL 中持久化存储过程调用
【发布时间】:2018-03-05 11:10:57
【问题描述】:

我正在使用 MySQL 开发在 WildFly 8 上运行的 EJB 3 应用程序。我需要更新实体 (User) 中的计数器 (receiptCounter),并决定通过存储过程调用尝试它以避免竞争条件。

这就是我创建存储过程的方式:

DELIMITER $$
CREATE PROCEDURE increment_receipt_counter
(
   IN userID_in INT
)
BEGIN
    UPDATE User SET receiptCounter = receiptCounter + 1 WHERE id = userID_in;
    SELECT receiptCounter AS receiptCounter_new FROM User WHERE id = userID_in;
END
$$
DELIMITER ;

我是这样称呼它的:

import javax.persistence.EntityManager;
import javax.persistence.StoredProcedureQuery;
...
public int incrementReceiptsCounter(int userID) throws InvalidEntityException, UnauthorizedException
{
    StoredProcedureQuery q = entityManager.createStoredProcedureQuery("increment_receipt_counter");
    q.registerStoredProcedureParameter("userID_in", Integer.class, ParameterMode.IN);
    q.setParameter("userID_in", userID);
    q.executeUpdate();
    return (Integer)q.getSingleResult();
}

奇怪的是:当从 Java 调用时,该过程返回正确的新计数器值,但新值并没有被持久化在数据库中。例如,如果在调用过程之前数据库中的receiptCounter为1,Java中的过程调用返回2,但数据库中的User表仍然显示值为1。当我直接从MySQL命令行调用过程时,它工作得很好。我做错了什么?

【问题讨论】:

  • 缺少提交?

标签: mysql stored-procedures ejb wildfly


【解决方案1】:

在 mysql 命令行中 auto commit 可能已启用,这意味着您的更新将自动持久化。

在 java 连接中,您可能禁用了auto commit,因此不会提交更新,但与update 在同一事务中运行的select 仍会返回更新后的值。

但是,如果你想处理并发,那么你应该先有一个select ... for update 来锁定计数器,然后更新值。

【讨论】:

  • 只是关于事务的说明,如果他使用的是用户管理的事务,那么可能会发生这种情况。如果他使用的是容器管理事务,那么应该自动调用自动提交,问题可能出在其他地方
猜你喜欢
  • 2015-11-02
  • 1970-01-01
  • 2012-06-15
  • 2011-01-05
  • 2016-07-08
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 2010-10-26
相关资源
最近更新 更多