J'utilise EclipseLink 2.3.0. J'ai une méthode que j'appelle depuis un test unitaire (donc en dehors d'un conteneur, pas de JTA) qui ressemble à ceci :
EntityManager em = /* get an entity manager */;
em.getTransaction().begin();
// make some changes
em.getTransaction().commit();
Les changements n'étaient PAS persistés dans la base de données, j'ai regardé cela pendant longtemps et j'ai finalement réalisé que EntityManager.getTransaction() retournait en fait une NOUVELLE EntityTransaction, au lieu de la même dans les deux appels. L'effet est que le premier appel crée une nouvelle transaction et la démarre, et que le second appel crée une AUTRE transaction et la valide. Comme la première transaction n'a jamais été validée, les modifications ne sont pas sauvegardées. Nous avons vérifié cela de la manière suivante :
log.info(em.getTransaction().toString());
log.info(em.getTransaction().toString());
Ce qui a donné lieu aux messages suivants :
INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl@1e34f445
INFO: org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl@706a4d1a
Les deux ID d'objets différents permettent de vérifier qu'il existe deux instances différentes. Modifier le code comme suit :
EntityManager em = /* get an entity manager */;
EntityTransaction tx = em.getTransaction();
tx.begin();
// make some changes
tx.commit();
... a remédié au problème. Maintenant, lorsque j'exécute le code, je vois les instructions SQL générées pour effectuer le travail sur la base de données, et en regardant dans la base de données, les données ont été modifiées.
J'ai été un peu surpris par ce résultat, car j'ai vu de nombreux exemples de code en ligne (pour JPA en général et pour EclipseLink en particulier) qui recommandent le code que nous avons utilisé pour gérer les transactions. J'ai cherché très loin des informations spécifiques à ce sujet, mais je n'ai rien trouvé. Que se passe-t-il donc ?
J'ai cherché dans les spécifications JPA quelque chose qui spécifie exactement ce que fait getTransaction() et ce n'était pas spécifique si la transaction est nouvelle ou identique. Existe-t-il un paramètre dans persistence.xml qui contrôle cela ? Le comportement est-il spécifique à chaque implémentation de la spécification JPA ?
Merci beaucoup pour toute information ou conseil.