Warum CMT Begehen am Ausgang der EJB-Methode, bei der transaction-Attribut ist "Erforderlich"?
Ich bin immer zu finden, dass meine bereits vorhandene Transaktion ist immer verpflichtet, in jeder Methode einer EJB markiert @ejb.transaction
type="Required"
. Kann das richtig sein?
Meine Erwartung ist, eine EJB "erfordern" eine Transaktion bedeutet: wenn es eines gibt es schon, es wird höflich lassen es uncommitted wenn Sie getan werden, also, wer aufgerufen wird begin() weiterhin verwenden können, es für weitere Operationen vor dem Aufruf commit()
oder rollback()
. [Natürlich, wenn es keine Transaktion in den ersten Platz, dann die EJB-Methode aufrufen würden beide begin()
und commit()
/rollback()
.]
Ist meine Erwartung falsch, oder sollte ich suchen für eine Konfigurations-Fehler?
Es relevant sein könnte, um hinzufügen, dass ich mit Hibernate 3 innerhalb der EJB. Ich bin den Erhalt einer UserTransaction vor dem Aufruf der EJB-Methode. Die EJB-generierten wrapper ruft ServerTransaction.commit()
auf die Ausfahrt, die Hibernate hakt und nutzt die Gelegenheit, um in der Nähe seiner Sitzung. Die Fehler ich erhalte, ist ein Hibernate lazy loading exception, da die Sitzung wird geschlossen, wenn ich versuche, auf Getter auf ein Hibernate-persistent-Objekt. So technisch bin ich nicht 100% sicher, ob die ServerTransaction.commit()
beobachtete ich unbedingt verpflichtet, die UserTransaction
begann ich (vielleicht ServerTransaction.commit()
nicht immer tatsächlich Folgen Sie durch mit einem "real" Begehen?), aber wenn es nicht -- dann auf welcher Grundlage ist Hibernate die Session geschlossen wird?
Update: ich glaube, dass meine Annahmen oben richtig war, aber meine Beobachtungen waren ein bisschen ab. Siehe unten für meine selbst gelieferten Antwort.
- "Wenn es eines gibt es schon, es wird höflich auf, lassen Sie es unverbindlich." Sind Sie sicher, dass Ihre Wahrnehmung hier? Von Ihr akzeptiert die Antwort, "Die
UserTransaction
ich begann, blieb offen, aber CMT erstellt eine neue Transaktion, bei der Einreise in die EJB-Methode, trotz der "Required" - Attribut." Dies ist ein Versuch, erstellen Sie ein weiteres geschachtelte Transaktionen und sollte stattdessen zu einer Ausnahme führen, wie --javax.transaction.NotSupportedException: Nested transaction not supported.
werden, da verschachtelte Transaktionen werden nicht unterstützt in Java EE. Ich habe irregeführt vollständig über das, was ich bereits wusste, über CMT und BMT. - Können Sie sich erinnern, das test-Szenario verwendet Vieren her?
- Ich erinnere mich an die Validierung in mehrfacher Hinsicht sowohl, dass mein UserTransaction blieb offen und der CMT Transaktion ein commit ausgeführt wurde, auf exit aus dem container-verwalteten EJB. Dieses Verständnis erlaubt mir, um Platz für die situation erfolgreich, wenn nicht ordnungsgemäß. Ich habe nichts gefunden, um zu zeigen, dass WL hatte erwiesen, Verhalten sich anders (beachten Sie, dass die tests angeführt von DavidBlevens verwendet OBLIGATORISCHEN ihm zufolge nicht ERFORDERLICH, da wurde mein Fall). Dies war 3-4 Verträge gemeldet, so dass ich kann Ihnen nicht mehr als das, sorry.
- Ich entschuldige mich für die Rechtschreibfehler von @DavidBlevins. Anscheinend kann ich nicht mehr reparieren, weil es 5 Minuten vergangen sind.
Du musst angemeldet sein, um einen Kommentar abzugeben.
ERFORDERLICH sein kann, böse
Ich persönlich mag es nicht die gewünschte Transaktion Attribut, und würde dringend davon abgeraten, seine Verwendung.
Träge Transaktionen anlegen (das ist, was ERFORDERLICH macht), führt nicht wirklich zu wissen, Wann und wo eine Transaktion tatsächlich gestartet werden, und wenn es zu Begehen. Das ist nicht eine gute Sache. Die Menschen sollten explizit design-Transaktions-Grenzen.
OBLIGATORISCH und UserTransaction Seelenverwandte sind
Ihrem Wunsch, eine
UserTransaction
ist sehr gut und hat Arbeit mit CMT-da ist kein Unterschied zwischen einer JTA-Transaktion gestartet wurde über die UserTransaction durch den mitgelieferten Behälter oder eine JTA-Transaktion gestartet, die für Sie durch den container.Den Ansatz, den ich empfehlen würde, ist die Umstellung aller ERFORDERLICHEN Nutzung zu ZWINGEND. Mit VERBINDLICHEN der container wird nicht starten Transaktionen für Sie. Stattdessen wird es schützen Sie Ihr bean, indem sichergestellt wird es nicht aufgerufen werden, es sei denn, eine Transaktion ausgeführt wird. Dies ist eine erstaunliche und selten genutzter Funktion. OBLIGATORISCH ist der beste Freund eines jeden, der will zur Schaffung eines wirklich deterministischen Transaktions-app und auch durchzusetzen. Mit diesem setup Sie könnten fallen in der Liebe mit CMT.
In diesem Szenario Sie starten Sie die Transaktionen mit
UserTransactions
und dann den container ist wie Ihre große bodyguard treten die Menschen an den Straßenrand, es sei denn, Sie haben entsprechend begonnen, eine Transaktion, bevor Sie versuchen, aufrufen von code.Überlegungen
@Resource UserTransaction
erhalten Sie die Benutzer-Transaktion mittels Injektionjava:comp/UserTransaction
erhalten Sie die Benutzer-Transaktion, die über lookup -@TransactionAttribute(MANDATORY)
verwendet, die auf Klassen-Ebene, beeinflussen die Methoden, die genaue Klasse (d.h. diefooClass.getDecaredMethods()
Methoden). Methoden der super-Klassen und-Unterklassen, wird standardmäßig@TransactionAttribute(REQUIRED)
es sei denn, diese Klassen sind explizit annotiert@TransactionAttribute(MANDATORY)
userTransaction.begin()
unduserTransaction.commit()
und dabei die zugehörige exception-handling, berücksichtigen@TransactionAttribute(REQUIRES_NEW)
. Ihre Transaktions-Grenzen werden weiterhin dokumentiert und explizit.RuntimeException
s geworfen von einer Methode der CMT-bean wird der Transaktion verursacht werden, gekennzeichnet rollback, auch wenn Sie fangen und behandeln der Ausnahme in der aufrufenden code. Verwenden@ApplicationException
deaktivieren Sie diese auf einer Fall-zu-Fall-basis für kundenspezifische runtime-exception-Klassen.Verlieren Ihre Transaktion Kontext
Ein paar Dinge, die verursachen können Ihre in-progress-Transaktion zu beenden, auszusetzen oder anderweitig nicht weitergegeben an die aufgerufene bean.
EntityTransaction
oderjava.sql.Connection.commit()
wird umgehen, Transaktions-management.Ist bei genauerem hinsehen eine andere Antwort als die oben vorgeschlagenen. Was ich tatsächlich sehen, ist, dass die UserTransaction ich begann, blieb offen, aber CMT erstellt eine neue Transaktion, bei der Einreise in die EJB-Methode, trotz der "Required" - Attribut.
Ich glaube, das ist passiert, weil ich die Regeln gebrochen. 🙂 Sie sollen nicht den Zugriff auf die UserTransaction-API bei Verwendung von CMT. CMT fröhlich ignoriert meine UserTransaction und begann seine eigene, nachdem er seinen Platz eingenommen, als der Schiedsrichter alle transaktionsgrenzen. Seit dem Start der Transaktion, commit es auch, und natürlich ließ mein UserTransaction unberührt.
Scheint spröde und dumm zu mir, vielleicht eine naive Meinung, aber die scheint im Einklang mit den "Regeln" wie ich Sie lese. Ich weiß nicht, warum CMT wählt, nicht zu spielen schön mit UserTransactions begann auf einer höheren Ebene. Vielleicht zu zwingen Entwickler, um "das richtige tun, J2EE Sache" und erstellen Sie einen anderen session-bean-Schicht zu behandeln, die breitere Transaktionskontext. Diese funktionieren würde, da die CMT wäre die Verwaltung für die äußere Transaktion ein und deshalb wäre es gut mit der Anwerbung einer inneren Transaktionen, und ich glaube, in einem solchen Fall, dem "Dach" Transaktion wäre nicht verpflichtet, die von der inneren EJBs; CMT würde warten, bis die äußere Transaktion abgeschlossen ist, dann Begehen die ganze Sache. Es müsste, eigentlich.
Ich bin nicht in der Stimmung, mehr zu schaffen session EJBs, die schon im EJB-aufgebläht-app, aber es wäre die einzige Lösung, die kurzen rippen CMT in eine ganze Reihe von Orten, die ich lieber nicht berühren.
NClark, sollten Sie den folgenden code lief ich auf GlassFish 3.1.1. Ich hoffe, es wird in irgendeiner Weise helfen 🙂
Dieser EJB aufgerufen werden können, d.h. von Singleton EJB mit @Startup sofort zu sehen wie Ihr DA reagieren wird.
Auf Glassfish 3.1.1, Sie kommen mit dem folgenden Ergebnis:
Prost!
Das ist, wie CMT-verwaltete Transaktionen arbeiten. Der container automatisch die Transaktion ein commit ausgeführt, wenn die business-Methode gibt. Wenn Sie nicht' nicht, die dieses Verhalten verwenden, BMT statt CMT.