2017-09-24 4 views
0

Je développe une application EJB 3 fonctionnant sur un serveur WildFly 8 avec MySQL. J'ai besoin de mettre à jour un compteur (receiptCounter) au sein d'une entité (User) et j'ai décidé de l'essayer avec un appel de procédure stockée pour éviter les conditions de course.Appel de procédure stockée WildFly non persistante dans MySQL

Voilà comment je créé la procédure stockée:

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 ; 

Voici comment je l'appelle:

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(); 
} 

La chose étrange est: Quand elle est appelée à partir de Java, la procédure renvoie la nouvelle correcte valeur du compteur, mais la nouvelle valeur n'est pas persistante dans la base de données. Par exemple, si receiptCounter était 1 dans la base de données avant d'appeler la procédure, l'appel de procédure en Java renvoie 2, mais la table User dans la base de données affiche toujours la valeur 1. Lorsque j'appelle la procédure directement depuis la ligne de commande MySQL, ça fonctionne très bien. Qu'est-ce que je fais mal?

+0

Manque de validation? – Shadow

Répondre

0

Dans la ligne de commande mysql, auto commit peut être activé, ce qui signifie que votre mise à jour est conservée automatiquement.

Dans la connexion java vous désactivez probablement le auto commit donc la mise à jour n'est pas engagée, mais le select en cours d'exécution dans la même transaction que le update, retourne toujours la valeur actualisée. Toutefois, si vous voulez gérer la simultanéité, vous devez d'abord select ... for update verrouiller le compteur, puis mettre à jour la valeur.

+0

Juste une note sur la transaction, s'il utilise une transaction gérée par l'utilisateur, alors ce scénario peut se produire. S'il utilise une transaction gérée par conteneur, la validation automatique doit être appelée automatiquement et le problème peut se situer ailleurs – maress