2017-09-24 10 views
0

MySQLでWildFly 8で実行されるEJB 3アプリケーションを開発しています。エンティティ(User)内のカウンタ(receiptCounter)を更新する必要があり、競合状態を回避するためにストアドプロシージャコールを試行することに決めました。WildFlyはMySQLでストアドプロシージャコールを持続しません

これは私がストアドプロシージャを作成する方法である:これは私がそれを呼び出す方法です

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から呼び出された場合、手順が正しい新しいを返します。新しい値はデータベースに保持されません。たとえば、プロシージャを呼び出す前にDB内のreceiptCounterが1だった場合、Javaのプロシージャ・コールは2を返しますが、DB内のUserテーブルの値は1になります。MySQLコマンドラインからプロシージャを直接呼び出すと、それはうまく動作します。私は間違って何をしていますか?

+0

コミットがありませんか? – Shadow

答えて

0

mysqlコマンドラインでauto commitが有効になっている可能性があり、更新が自動的に持続されることを意味します。

auto commitのJava接続では、更新はコミットされませんが、updateと同じトランザクションで実行されているselectは、更新された値を返します。

ただし、同時実行性を処理する場合は、最初にselect ... for updateにカウンタをロックしてから値を更新する必要があります。

+0

ユーザー管理のトランザクションを使用している場合は、トランザクションのメモだけが必要です。このシナリオが発生する可能性があります。コンテナ管理のトランザクションを使用している場合は、自動コミットを自動的に呼び出す必要があり、問題は他の場所にある可能性があります – maress

関連する問題