Warum speichert @Transactional automatisch in der Datenbank?

8

Ich habe eine Methode mit @Transactional markiert. Ich erhalte ein Objekt aus meiner DB, ändere ein Feld und kehre dann von der Methode zurück. Ohne mein Objekt zu speichern, wird die Datenbank trotzdem aktualisiert, was merkwürdig ist.

Könnten Sie mir bitte sagen, wie ich dieses Beahvior vermeiden kann?

    
Rachidon 04.02.2014, 12:23
quelle

2 Antworten

8

Dieses Verhalten ist einer der Hauptzwecke der Transaktionalität.

Bevor die Transaktionsmethode zurückgegeben wird, wird die Transaktion festgeschrieben, was bedeutet, dass alle Änderungen an den verwalteten Entitäten in die Datenbank übernommen werden.

Wenn ein Fehler auftritt, wird die Transaktion zurückgesetzt, dh es werden keine Änderungen an der Datenbank vorgenommen.

Wahrscheinlich erhalten Sie LazyInitializationException , wenn Sie versuchen, auf eine träge geladene Eigenschaft zuzugreifen, wahrscheinlich auf eine Sammlung aus einer Entität. Lazy-loded-Eigenschaften werden nicht instanziiert, wenn Sie eine Entität von DB abrufen.

Wenn Sie auf eine träge geladene Eigenschaft in einer Transaktion zugreifen, erstellt der Persistenzanbieter eine Abfrage, instanziiert das Ergebnis und hängt es an die "übergeordnete" Entität an.

BEARBEITEN: Wenn Sie möchten, dass die faulen Eigenschaften geladen werden UND in der Lage sind, Ihre Entity zu ändern, ohne dass die Änderungen in der DB persistent sind, können Sie die Entität mit Fetch-Joins für die faulen Eigenschaften holen.

%Vor%

Fahren Sie dann mit einer der von @orid beschriebenen Methoden fort.

Wenn Sie keine Fetch-Joins verwenden, müssen Sie noch während der Transaktion auf die träge geladenen Eigenschaften zugreifen:

%Vor%

Beachten Sie den Aufruf von size() . Der Aufruf des Getters ist nicht genug, da Sie einen Proxy erhalten. Sie müssen eine Operation ausführen, die die tatsächlichen Daten von der Eigenschaft benötigt.

    
kostja 04.02.2014, 12:31
quelle
6

Dies ist ein normales JPA-Verhalten.

Sobald Sie ein Objekt über find() abgerufen haben, wird dieses Objekt als angehängt betrachtet oder gehört zu einem Persistenzkontext. Sobald Sie die Methode verlassen, löst @Transactional einen Spring-Transaktionsverwaltungsaspekt aus, der jedes "schmutzige" Objekt in die Datenbank löscht und die Transaktion festschreibt. Da Ihr Objekt bereits im Kontext des Persistenzkontexts und der Transaktion geändert wurde, werden die Änderungen in der Datenbank gespeichert, auch wenn Sie nicht explizit eine Speichermethode aufrufen müssen.

Wenn Sie Ihr Objekt ändern möchten, ohne die Datenbank zu beeinflussen, haben Sie zwei Möglichkeiten:

  1. Aktualisieren Sie das Feld, nachdem Sie von der mit @Transactional annotierten Methode zurückgekehrt sind.
  2. Wenn Sie die Methode verwenden, rufen Sie los zum Entity Manager
Ori Dar 04.02.2014 12:39
quelle

Tags und Links