web-dev-qa-db-fra.com

Sauvegarde transactionnelle sans appeler la méthode de mise à jour

J'ai une méthode annotée avec @Transactional. Je récupère un objet de ma base de données Oracle, modifie un champ, puis retourne de la méthode. J'ai oublié de sauvegarder l'objet, mais j'ai découvert que la base de données était mise à jour de toute façon.

applicationContext

<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

ma méthode

@Transactional
public void myMethod(long id) {
    MyObject myObj = dao.getMstAttributeById(id);
    myObj.setName("new name");
    //dao.update(myObj);
}

ma question est la suivante: pourquoi MyObject est-il maintenu dans la base de données?

31
John LaFleur

Hibernate détectera automatiquement les modifications apportées aux entités persistent et mettra à jour la base de données en conséquence. Ce comportement est documenté dans chapitre 11 du manuel de référence d'Hibernate. La partie pertinente se lit comme suit:

Hibernate définit et prend en charge les états d'objet suivants:

  • Transient - un objet est transitoire s'il vient d'être instancié à l'aide du nouvel opérateur et s'il n'est pas associé à une session Hibernate. Il n'a pas de représentation persistante dans la base de données et aucune valeur d'identificateur n'a été attribuée. Les instances transitoires seront détruites par le ramasse-miettes si l'application ne contient plus de référence. Utilisez la session Hibernate pour rendre un objet persistant (et laissez Hibernate se charger des instructions SQL à exécuter pour cette transition).

  • Persistent - une instance persistante a une représentation dans la base de données et une valeur d'identificateur. Il a peut-être été sauvegardé ou chargé, mais il est par définition dans le cadre d'une session. Hibernate détectera toutes les modifications apportées à un objet dans un état persistant et synchronisera cet état avec la base de données à la fin de l'unité de travail. Les développeurs n'exécutent pas les instructions UPDATE manuelles ni les instructions DELETE lorsqu'un objet doit être rendu transitoire.

  • Detached - une instance détachée est un objet qui a été persistant, mais sa session a été fermée. La référence à l'objet est toujours valide, bien entendu, et l'instance détachée peut même être modifiée dans cet état. Une instance détachée peut être rattachée à une nouvelle session ultérieurement, ce qui la rend (ainsi que toutes les modifications) persistante. Cette fonctionnalité active un modèle de programmation pour les unités de travail de longue durée nécessitant du temps de réflexion de l'utilisateur. Nous les appelons transactions d’application, c’est-à-dire une unité de travail du point de vue de l’utilisateur.

51
meriton

Si vous utilisez un JPA, la spécification indique que si votre entité est dans est géré par l'état (et c'est ce que vous faites en récupérant les données de la DAO dans une transaction active), toutes les modifications apportées à cette être reflété dans la base de données pendant la transaction commit .

Donc, en d'autres termes - cela n'a pas vraiment d'importance si vous appelez l'opération de mise à jour ou non, car la validation de la transaction annulera les modifications apportées à la base de données.

5
Piotr Nowicki

J'ai constaté que le fait d'empêcher les mises à jour automatiques de la base de données était un processus en deux étapes.

Etape I: 

getSession().setFlushMode(FlushMode.MANUAL) // [FlushMode.NEVER is depracated in 4.x]

Étape II: 

getSession().clear(); //This will actually discard all changes
1
Sagar Kapadia

J'ai utilisé @Transactional(readOnly = true) pour le résoudre

0
Sandy