2009-11-23 3 views
8

Nous utilisons l'implémentation Toplink de JPA + Spring + EJB. Dans l'un de nos EJBs nous avons quelque chose comme ceci:JPA - enregistrement des modifications sans persist()

public void updateUser(long userId, String newName){ 
    User u = em.get(User.class, userId); 
    u.setName(newName); 
    // no persist is invoked here 
} 

Ainsi, fondamentalement cette méthode de updateUser est censé mettre à jour le nom de l'utilisateur avec l'identifiant donné. Mais l'auteur de cette méthode a oublié d'invoquer em.persist (u);

Et la chose la plus étrange est que cela fonctionne bien. Comment ça peut être? J'étais sûr à 100% que sans invoquer em.persist() ou em.merge() il n'y a aucun moyen que des changements aient pu être sauvegardés dans la base de données. Pourraient-ils? Y a-t-il un scénario où cela pourrait arriver?

Merci

Répondre

11

Vous travaillez avec une entité gérée. Si l'entité ne se détache pas parce que son gestionnaire d'entités est fermé, toutes les modifications apportées à l'entité sont répercutées dans la base de données lorsque la session est vidée/fermée et que la transaction est validée.

De l'Java EE tutorial:

L'état des entités persistantes est synchronisé sur la base de données lorsque l'opération avec laquelle l'entité est commits associés.

Modifier pour plus de clarté et une explication: Donc, il y a trois modes distincts qu'une entité pourrait être en cours de son cycle de vie:

  • Unsaved: L'entité a été instancié, mais persist() n'a pas été appelé encore.
  • Géré: L'entité a été conservée en utilisant persist() ou chargée depuis la base de données et est associée à une session de gestionnaire d'entités. Toutes les modifications apportées à l'entité sont reflétées dans la base de données lorsque la session du gestionnaire d'entités est vidée.
  • Détaché: La session du gestionnaire d'entités de l'entité a été fermée. Les modifications apportées à l'entité ne seront pas reflétées automatiquement dans la base de données, mais peuvent être fusionnées explicitement à l'aide de la commande merge().
+0

Merci. Cela a beaucoup aidé! J'ai toujours pensé que l'appel à em.persist() est requis, même si l'objet est associé à EntityManager actuel. – anthony

+0

Bizarre: Dans ma configuration, j'ai une référence à une entité gérée. Ensuite, je change l'état de cette entité. Ensuite, j'appelle 'entityManager.flush()'. Dans le cas où cela est en cours d'exécution dans une transaction, l'état modifié ** de l'entité est écrit ** dans la base de données. Dans le cas où cela est en cours sans transaction, l'état modifié de l'entité ** n'est pas écrit ** dans la base de données. L'affirmation suivante est donc vraie?: * "Il doit toujours y avoir une validation de transaction ou un appel' entityManager.persist (obj) 'pour écrire le dernier état de' obj' dans la base de données. " J'utilise JPA 2.0 avec Hibernate (4.1.7.Final)) – Abdull

+0

@Abdull, oui, la spécification JPA ne définit aucun comportement d'autocommit, donc vous avez besoin d'une transaction en cours ou rien n'est écrit dans la base de données. – Henning

Questions connexes