Ich wollte ein Objekt ( ReportBean
) in der Datenbank beibehalten, aber ich habe eine Fehlermeldung erhalten:
Hier ist ein bisschen Code:
Einheit
%Vor% benutzerdefinierte Annotation zum Zulassen der EntityManager-Injektion (mit @Inject
)
EntityManager-Anbieter
%Vor% ValidateReportAction-Klasse - verfügt über eine Methode, um den Bericht in der Datenbank persistent zu machen.
Ich versuche bei den wichtigsten Importen zu bleiben.
Wenn ich die EntityManager
verwenden möchte, um eine Abfrage (oder NamedQuery wie im Beispiel) zu erstellen, funktioniert alles.
Q
: Hier in der createReport()
-Methode, wenn der em.persist ausgeführt wird, ist der Fehler aufgetreten. Ich dachte, dass die Transaktion vom Container verwaltet wird ( CMT
), aber jetzt denke ich, dass ich falsch liege. Wo habe ich einen Fehler gemacht? Was ist der richtige Weg, um CMT zu implementieren?
Hier ist auch meine persistence.xml
-Konfiguration:
Bitte lassen Sie mich wissen, wenn etwas in meiner Frage nicht klar ist.
Wo habe ich einen Fehler gemacht?
Sie scheinen zu glauben, dass @TransactionManagement(TransactionManagementType.CONTAINER)
Container-verwaltete Transaktionen aktiviert und @TransactionAttribute(TransactionAttributeType.REQUIRED)
dann eine Transaktion in einer Methode für eine nicht EJB Bean aktiviert.
Dies ist jedoch (noch) nicht in Java EE möglich.
Die Annotation @TransactionManagement
wird nur verwendet, um eine EJB-Bean, die CMT bereits aus dem Container bezieht, in BMT (Bean Managed Transactions) umzuschalten. Die CONTAINER
-Konstante ist mehr der Vollständigkeit halber, es ist das, was Sie bekommen, wenn Sie die Annotation komplett weglassen.
Ebenso wird @TransactionAttribute
keine Transaktionen für eine Methode auf einer Nicht-EJB-Bean aktivieren. Die Annotation selbst existiert, um die Transaktion in einen anderen Typ zu wechseln (wie REQUIRES_NEW). Für ein EJB wird es normalerweise nicht einmal benötigt, da auch dies der Standard ist und auch hauptsächlich der Vollständigkeit dient, aber auch dazu verwendet werden kann, eine einzelne Methode auf REQUIRES zurückzusetzen, wenn Transaktionen auf Klassenebene geändert werden.
Was ist der richtige Weg, CMT zu implementieren?
Der richtige Weg besteht darin, ein Komponentenmodell zu verwenden, das CMT bereits aus dem Container bezieht, wie eine Stateless Session-Bean:
%Vor% Dann injiziere diese Bohne (mit @EJB
oder @Inject
) in deine benannten Beans und benutze sie. Alternativ kann diese Bean auch mit @Named
benannt werden, so dass sie direkt in EL verwendet werden kann, aber dies wird nicht immer empfohlen.
Die @Stateless
-Bohne erlaubt kein Scoping (es ist im Grunde 'invocation-scoped'), aber das @Stateful
-Modell kann als Session-Bereich definiert sein wie Ihre ursprüngliche Bean. Bei der gegebenen Funktionalität muss es jedoch nicht auf die Sitzung beschränkt sein. Wenn Sie dies nur für den Entity Manager getan haben, denken Sie daran:
Es gibt Möglichkeiten, etwas zu implementieren, das ein bisschen wie CMT mit CDI und JTA aussieht, aber wenn Sie echtes CMT wollen, dann ist dies im Moment der einzige Weg. Es ist geplant, die festen Komponentenmodelle wie Stateless, Stateful, Singleton und Message in individuelle (CDI) Annotationen zu zerlegen (siehe Ссылка und speziell für Ihre Frage Entkoppeln der @TransactionAttribute-Annotation vom EJB-Komponentenmodell ), aber dies ist nicht Es ist noch nicht passiert.
Update auf Java EE 7 (CDI 1.1), Sie können jetzt @Transactional verwenden, um den CMT in CDI-Beans zu aktivieren. Sie müssen EJB nicht mehr verwenden.
Referenz: JEE7: Tun EJB und CDI Bohnen Containergesteuerte Transaktionen unterstützen?
Sie haben Recht, aber in Ihrer Lösung erstellen Sie ein verschachteltes Transaktion, die vom aufrufenden Kontext isoliert ist. Leider konnte ich keine Lösung finden ein Transitionskontext wie dieser
%Vor%Tags und Links java-ee transactions cdi