Sollten Sie die platzieren @Transactional
in dem DAO
Klassen und/oder deren Methoden oder ist es besser, die aufrufenden Service-Klassen mit den DAO-Objekten zu kommentieren? Oder ist es sinnvoll, beide “Schichten” zu kommentieren?
Wohin gehört die Annotation @Transactional?
Thomas Einwaller
duffymo
Ich denke, Transaktionen gehören auf die Serviceebene. Es ist derjenige, der sich mit Arbeitseinheiten und Anwendungsfällen auskennt. Es ist die richtige Antwort, wenn Sie mehrere DAOs in einen Dienst eingefügt haben, die in einer einzigen Transaktion zusammenarbeiten müssen.
-
Ich stimme dem zu. Manchmal spielt es keine Rolle, aber manchmal können Sie davon profitieren, dass z. B. die Hibernate-Sitzung für die While-Transaktion überspannt wird, sodass sich alle geladenen Objekte im 1st-Level-Cache befinden und Sie die Objekte nicht erneut an die Sitzung anhängen müssen, plus faul geladen Eigenschaften funktionieren ohne Fuzz.
– dma_k
26. September 2010 um 18:47 Uhr
-
Kann eine globale Transaktion aus mehr als einer dieser @Transactional(propagation = Propagation.REQUIRED) bestehen? Oder @Transactional ist immer eine Grenze für eine Transaktion? Ich bin mir nicht sicher, ob ich es aus der Dokumentation habe, aber es scheint ein bisschen, dass Sie sogar Transaktionen erstellen können, die aus @Transactional-Methoden und allem, was darin läuft, bestehen
– Lisak
4. November 2010 um 23:56 Uhr
-
Ja, ich denke, das äußerste @Transactional ist dasjenige, das zur Grenze für die Transaktion wird, wenn Propagation.REQUIRED aktiviert ist.
– Duffymo
5. November 2010 um 0:10 Uhr
-
stackoverflow.com/questions/18498115/…
– Shahid Ghafoor
28. August 2013 um 21:06 Uhr
-
Wir müssen @Transactional nicht explizit erwähnen, wenn es sich um eine einzelne Arbeitseinheit handelt.
– Balaji Sudharsanam
21. Dezember 2020 um 17:46 Uhr
Im Allgemeinen stimme ich den anderen zu, dass Transaktionen normalerweise auf der Serviceebene gestartet werden (abhängig von der Granularität, die Sie natürlich benötigen).
Allerdings habe ich in der Zwischenzeit auch angefangen zuzufügen @Transactional(propagation = Propagation.MANDATORY)
zu meinem DAO-Layer (und anderen Layern, die keine Transaktionen starten dürfen, sondern vorhandene benötigen), da es viel einfacher ist, Fehler zu erkennen, bei denen Sie vergessen haben, eine Transaktion im Aufrufer (z. B. dem Dienst) zu starten. Wenn Ihr DAO mit obligatorischer Weitergabe annotiert ist, erhalten Sie eine Ausnahme, die besagt, dass keine aktive Transaktion vorhanden ist, wenn die Methode aufgerufen wird.
Ich habe auch einen Integrationstest, bei dem ich alle Beans (Bean-Postprozessor) auf diese Anmerkung überprüfe und fehlschlage, wenn es eine gibt @Transactional
Annotation mit einer anderen Weitergabe als Mandatory in einer Bean, die nicht zur Dienstschicht gehört. Auf diese Weise stelle ich sicher, dass wir keine Transaktionen auf der falschen Ebene starten.
-
Sollte dies in der dao (interfaces) Schicht geschehen, in der dao impl. Schicht oder beides?
– Johann
13. März 2013 um 9:05 Uhr
-
Ich weiß nicht, ob es in diese Diskussion passt, aber ein weiterer Tipp könnte darin bestehen, @Transactional(readOnly = true) im dao impl in den nicht schreibenden Operationen hinzuzufügen.
– Maxivis
29. November 2013 um 0:07 Uhr
-
@Johan Spring empfiehlt, die Transaktionsanmerkungen auf die Implementierungsklassen anstatt auf die Schnittstellen zu setzen.
– Matthias G.
6. Dezember 2013 um 10:07 Uhr
-
Ich mag diese Idee sehr und versuche das auch für meine Projekte
– Thomas Einwaller
7. Februar 2014 um 11:27 Uhr
-
Lassen Sie mich sehen, ob ich es verstehe… sagen Sie, ich soll es tun?
@Transactional
auf der Dienstimplementierungsklasse, und ich sollte setzen@Transactional(propagation = MANDATORY)
auf der Implementierung der DAO-Klasse (Repository)?– Johann Henckel
7. Juni 2017 um 21:52 Uhr
Michael Willes
Transaktionale Anmerkungen sollten um alle Operationen herum platziert werden, die untrennbar miteinander verbunden sind.
Ihr Aufruf lautet beispielsweise „Passwort ändern“. Das besteht aus zwei Operationen
- Änder das Passwort.
- Auditieren Sie die Änderung.
- E-Mail an den Client, dass sich das Passwort geändert hat.
Wenn die Prüfung oben fehlschlägt, sollte dann auch die Kennwortänderung fehlschlagen? Wenn dies der Fall ist, sollte die Transaktion zwischen 1 und 2 liegen (also auf der Serviceebene). Wenn die E-Mail fehlschlägt (wahrscheinlich sollte sie eine Art Ausfallsicherung haben, damit sie nicht fehlschlägt), sollte sie dann die Kennwortänderung und die Prüfung rückgängig machen?
Dies sind die Art von Fragen, die Sie sich stellen müssen, wenn Sie entscheiden, wo Sie die platzieren möchten @Transactional
.
Die richtige Antwort für traditionelle Spring-Architekturen besteht aus den bereits beschriebenen Gründen darin, die Transaktionssemantik auf die Dienstklassen zu übertragen.
Ein aufkommender Trend im Frühjahr geht hin domänengesteuertes Design (DDD). Spring Roo ist ein gutes Beispiel für diesen Trend. Die Idee ist, die Domänenobjekt-POJOs viel reichhaltiger zu machen, als sie es auf typischen Spring-Architekturen sind (normalerweise sind sie es anämisch) und insbesondere Transaktions- und Persistenzsemantik auf die Domänenobjekte selbst zu übertragen. In Fällen, in denen lediglich einfache CRUD-Vorgänge erforderlich sind, arbeiten die Webcontroller direkt auf den Domänenobjekt-POJOs (sie fungieren in diesem Kontext als Entitäten), und es gibt keine Dienstebene. In Fällen, in denen zwischen Domänenobjekten eine Art Koordination erforderlich ist, können Sie dies mit einer Service-Bean erledigen @Transaction
nach Überlieferung. Sie können die Transaktionsweitergabe für die Domänenobjekte auf etwas wie festlegen REQUIRED
sodass die Domänenobjekte alle vorhandenen Transaktionen verwenden, z. B. Transaktionen, die am Service-Bean gestartet wurden.
Technisch verwendet diese Technik AspectJ und <context:spring-configured />
. Roo verwendet AspectJ-Intertyp-Definitionen, um die Entitätssemantik (Transaktionen und Persistenz) von den Domänenobjekten (im Wesentlichen Felder und Geschäftsmethoden) zu trennen.
Hammarrücken
Der Normalfall wäre das Kommentieren auf Service-Layer-Ebene, aber das hängt wirklich von Ihren Anforderungen ab.
Das Kommentieren auf einer Dienstebene führt zu längeren Transaktionen als das Kommentieren auf DAO-Ebene. Abhängig von der Transaktionsisolationsstufe können Probleme auftreten, da gleichzeitige Transaktionen die Änderungen der anderen nicht sehen, z. WIEDERHOLBARES LESEN.
Durch das Kommentieren der DAOs werden die Transaktionen so kurz wie möglich gehalten, mit dem Nachteil, dass die Funktionalität, die Ihre Serviceschicht bereitstellt, nicht in einer einzigen (rollbackfähigen) Transaktion ausgeführt wird.
Es ist nicht sinnvoll, beide Schichten zu kommentieren, wenn der Ausbreitungsmodus auf Standard eingestellt ist.
naXa
Ich stelle die @Transactional
auf der @Service
Schicht und Set rollbackFor
jede Ausnahme u readOnly
um die Transaktion weiter zu optimieren.
Standardmäßig @Transactional
werde nur suchen RuntimeException
(Ungeprüfte Ausnahmen), indem Rollback auf gesetzt wird Exception.class
(Überprüfte Ausnahmen) Es wird für jede Ausnahme ein Rollback ausgeführt.
@Transactional(readOnly = false, rollbackFor = Exception.class)
martoncsukas
Für Transaktionen auf Datenbankebene
meistens habe ich verwendet @Transactional
in DAO’s nur auf Methodenebene, daher kann die Konfiguration spezifisch für eine Methode / mit Standard sein (erforderlich)
-
DAO-Methode zum Abrufen von Daten (select .. ) – nicht erforderlich
@Transactional
Dies kann zu einem gewissen Overhead führen, da Transaktionsinterceptor / und AOP-Proxy ebenfalls ausgeführt werden müssen. -
Die Methoden von DAO, die einfügen / aktualisieren, werden erhalten
@Transactional
sehr guter Blog auf transaktional
Für Anwendungsebene –
Ich verwende Transaktionslogik für Geschäftslogik, die ich im Falle eines unerwarteten Fehlers zurücksetzen möchte
@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){
try {
//service logic here
} catch(Throwable e) {
log.error(e)
throw new MyApplicationException(..);
}
}
-
+1 sehr schöner Artikel über
Transactional
inJava
– Eiche
5. März 2014 um 9:17 Uhr