J'ai un test d'intégration d'un DAO dans lequel j'utilise un EntityManager partagé (via Spring, en utilisant SharedEntityManagerCreator). La classe de test est marquée comme @Transactional, de même que la méthode DAO en cours de test.JPA: EntityManager.find() renvoie-t-il toujours la même référence d'objet pour la même clé?
Dans la classe d'essai et le DAO je retreiving une entité utilisateur comme suit:
User user = em.find(User.class, "test");
Dans la configuration de mon test, je l'ai modifié l'objet utilisateur, mais je ne voyais pas la modification dans le DAO lorsque le test est venu à courir. Il s'est avéré que les deux références ne se référaient pas au même objet; Je l'ai prouvé dans ma classe de test en utilisant:
System.out.println("User objects equal = " + (user == dao.getUser()));
Ceci a été imprimé faux. Je m'attendais à ce que chaque appel à un EntityManager utilisant la même clé renvoie la même référence d'objet, et a été surpris (et un peu alarmé!) De découvrir que ce n'était pas le cas. Quelqu'un peut-il nous éclairer à ce sujet? J'ai refacturé mon code donc ce n'est pas vraiment un problème (le DAO ne devrait pas avoir l'objet User dedans de toute façon) mais j'aimerais quand même mieux le comprendre.
Merci!
Java 1.6u22, Toplink Essentials 2.0.1, Spring 2.5.6
axtavt est correct. Lorsque EntityManager est fermé, le contexte de persistance associé à celui-ci est récupéré. Si votre instance de EntityManager est fournie automatiquement par le conteneur avec la transaction, alors vos appels à em.find() retourneront toujours le même objet physique pour la même clé primaire tant que la même transaction (et EntityManager) sont toujours ouvrir. Si vous avez besoin d'un EntityManager avec une durée de vie plus longue, vous avez la possibilité d'utiliser un EntityManager géré par l'application au lieu d'un Entité Manager géré par le conteneur, mais avec un travail supplémentaire. –
Je vois, merci pour vos réponses. Je suis sûr qu'il n'y a qu'une seule transaction partagée par mon test et mon dao, car les méthodes annotées @Before et @After sont incluses par l'annotation @Transactional; Les journaux Toplink affichent également une seule transaction. Donc je suppose que je ne dois pas avoir le même EntityManager dans la classe de test et le DAO. Existe-t-il un moyen de savoir si deux EntityManagers sont identiques? Je sais que le EntityManager partagé que Spring me donne est en fait un proxy qui délègue les appels, donc je ne vois pas de manière évidente de vérifier. – Conan
@Conan: J'ai vérifié et découvert que les méthodes '@ Before' /' @ After' sont réellement exécutées dans la même transaction que '@ Test', donc' em.find() 'retourne les mêmes instances. Peut-être que votre problème a une autre cause. Vous pouvez enregistrer 'TransactionSynchronizationManager.getCurrentTransactionName()' pour vérifier l'identité de la transaction. – axtavt