Die Frage ist nicht privat oder öffentlich, die Frage lautet: Wie wird sie aufgerufen und welche AOP-Implementierung verwenden Sie?
Wenn Sie Spring Proxy AOP (Standard) verwenden, werden alle von Spring bereitgestellten AOP-Funktionen (wie @Transational
) nur berücksichtigt, wenn der Anruf über den Proxy erfolgt. - Dies ist normalerweise der Fall, wenn die mit Anmerkungen versehene Methode von einer anderen Bean aufgerufen wird .
Dies hat zwei Auswirkungen:
- Da private Methoden nicht von einer anderen Bean aufgerufen werden dürfen (Ausnahme: Reflection), wird ihre
@Transactional
Annotation nicht berücksichtigt.
- Wenn die Methode öffentlich ist, aber von derselben Bean aufgerufen wird, wird sie auch nicht berücksichtigt (diese Anweisung ist nur korrekt, wenn (Standard) Spring Proxy AOP verwendet wird).
@ Siehe Federreferenz : Kapitel 9.6 9.6 Proxy-Mechanismen
IMHO sollten Sie anstelle der Spring Proxies den AspektJ-Modus verwenden, um das Problem zu lösen. Und die AspectJ-Transaktionsaspekte sind sogar in private Methoden eingebunden (auf Spring 3.0 geprüft).
Die Antwort auf Ihre Frage lautet "Nein" -
@Transactional
hat keine Auswirkung, wenn private Methoden mit Anmerkungen versehen werden. Der Proxy-Generator ignoriert sie.Dies ist im Spring Manual Kapitel 10.5.6 dokumentiert :
quelle
Standardmäßig
@Transactional
funktioniert das Attribut nur, wenn eine mit Anmerkungen versehene Methode für eine aus applicationContext erhaltene Referenz aufgerufen wird.Dies öffnet eine Transaktion:
Dies wird nicht:
Federreferenz: Verwenden von @Transactional
quelle
Ja, es ist möglich, @Transactional für private Methoden zu verwenden, aber wie andere bereits erwähnt haben, funktioniert dies nicht sofort. Sie müssen AspectJ verwenden. Ich brauchte einige Zeit, um herauszufinden, wie ich es zum Laufen bringen konnte. Ich werde meine Ergebnisse teilen.
Ich habe mich für das Weben zur Kompilierungszeit anstelle des Webens zur Ladezeit entschieden, da ich denke, dass dies eine insgesamt bessere Option ist. Außerdem verwende ich Java 8, sodass Sie möglicherweise einige Parameter anpassen müssen.
Fügen Sie zunächst die Abhängigkeit für aspectjrt hinzu.
Fügen Sie dann das AspectJ-Plugin hinzu, um das eigentliche Bytecode-Weben in Maven durchzuführen (dies ist möglicherweise kein minimales Beispiel).
Fügen Sie dies schließlich Ihrer Konfigurationsklasse hinzu
Jetzt sollten Sie @Transactional für private Methoden verwenden können.
Eine Einschränkung bei diesem Ansatz: Sie müssen Ihre IDE so konfigurieren, dass Sie AspectJ kennen. Andernfalls funktioniert die App möglicherweise nicht, wenn Sie sie über Eclipse ausführen. Stellen Sie sicher, dass Sie einen Test gegen einen direkten Maven-Build durchführen.
quelle
Wenn Sie eine private Methode in eine Transaktion einschließen müssen und aspectj nicht verwenden möchten, können Sie TransactionTemplate verwenden .
quelle
TransactionTemplate
Verwendung zu zeigen , aber bitte rufen Sie diese zweite Methode auf..RequiresTransaction
und nicht..InTransaction
. Nennen Sie Dinge immer so, wie Sie sie ein Jahr später lesen möchten. Ich würde auch argumentieren, wenn es wirklich eine zweite private Methode erfordert: Entweder den Inhalt direkt in die anonymeexecute
Implementierung einfügen oder wenn dies chaotisch wird, könnte dies ein Hinweis darauf sein, die Implementierung in einen anderen Dienst aufzuteilen, den Sie dann mit Anmerkungen versehen können@Transactional
.Spring Docs erklären das
Ein anderer Weg ist der Benutzer BeanSelfAware
quelle
BeanSelfAware
? Es sieht nicht aus wie eine FrühlingsklasseDie Antwort ist nein. Weitere Informationen finden Sie in der Spring-Referenz: Verwenden von @Transactional :
quelle
Genauso wie @loonis vorgeschlagen hat , TransactionTemplate zu verwenden, kann diese Hilfskomponente (Kotlin) verwendet werden:
Verwendung:
Ich weiß nicht, ob
TransactionTemplate
vorhandene Transaktionen wiederverwendet werden oder nicht, aber dieser Code tut es definitiv.quelle