Eine lange Frage, bitte nehmen Sie sie mit.
Wir verwenden Spring + JPA für eine Webanwendung. Mein Team debattiert über Injektion EntityManagerFactory
in den GenericDAO
(DAO basierend auf Generics etwas über die von AppFuse vorgesehen Linien, wissen wir nicht verwenden , JpaDaosupport
über die Injektion aus irgendeinem Grund) ein EntityManager
. Wir verwenden "anwendungsverwaltete Persistenz".
Die Argumente gegen das Injizieren von a EntityManagerFactory
sind, dass es zu schwer ist und daher nicht benötigt wird, das EntityManager
tut, was wir brauchen. Da Spring für jede Webanforderung eine neue Instanz eines DAO erstellen würde (ich bezweifle dies), treten keine Parallelitätsprobleme auf, da dieselbe EntityManager
Instanz von zwei Threads gemeinsam genutzt wird.
Das Argument für die Injektion von EFM ist, dass es eine gute Praxis ist, eine Fabrik im Griff zu haben.
Ich bin mir nicht sicher, welcher Ansatz der beste ist. Kann mich bitte jemand aufklären?
quelle
Antworten:
Die Vor- und Nachteile der Injektion von EntityManagerFactory gegenüber EntityManager sind in den Spring-Dokumenten hier aufgeführt . Ich bin mir nicht sicher, ob ich das verbessern kann.
Wenn Sie das sagen, gibt es einige Punkte in Ihrer Frage, die geklärt werden sollten.
Das ist nicht richtig. Wenn Ihr DAO eine Spring-Bean ist, handelt es sich um ein Singleton, sofern Sie es nicht über das
scope
Attribut in der Bean-Definition anders konfigurieren . Ein DAO für jede Anfrage zu instanziieren wäre verrückt.Dieses Argument hält nicht wirklich Wasser. Nach allgemeiner bewährter Praxis sollte einem Objekt die Mindestanzahl an Mitarbeitern injiziert werden, die es für seine Arbeit benötigt.
quelle
Ich lege nieder, was ich endlich gesammelt habe. Aus dem Abschnitt " Implementieren von DAOs basierend auf einfachem JPA " in der Frühjahrsreferenz:
Dies bedeutet, dass EntityManager-Instanzen gemäß den JPA-Spezifikationen nicht threadsicher sind. Wenn Spring sie jedoch verarbeitet, werden sie threadsicher gemacht.
Wenn Sie Spring verwenden, ist es besser, EntityManagers anstelle von EntityManagerFactory zu injizieren.
quelle
Ich denke, dies wurde bereits gut behandelt, aber nur um ein paar Punkte zu bekräftigen.
Wenn das DAO von Spring injiziert wird, ist es standardmäßig ein Singleton . Sie müssen den Bereich explizit auf Prototyp festlegen, um jedes Mal eine neue Instanz zu erstellen.
Der von @PersistenceContext injizierte Entity Manager ist threadsicher .
Davon abgesehen hatte ich einige Probleme mit einem Singleton-DAO in meiner Multithread-Anwendung.
Am Ende machte ich das DAO zu einer instanziierten Bohne und das löste das Problem.Während die Dokumentation eines aussagt, möchten Sie Ihre Anwendung wahrscheinlich gründlich testen.Nachverfolgen:
Ich denke, ein Teil meines Problems ist, dass ich benutze
@PersistenceContext(unitName = "unit", type = PersistenceContextType.EXTENDED)
Wenn Sie PersistenceContextType.EXTENDED verwenden, müssen Sie, wenn ich das richtig verstehe, die Transaktion manuell schließen. Weitere Informationen finden Sie in diesem Thread.
Ein weiteres Follow-up:
Die Verwendung eines instanziierten DAO ist eine äußerst schlechte Idee. Jede Instanz des DAO verfügt über einen eigenen Persistenz-Cache, und Änderungen an einem Cache werden von anderen DAO-Beans nicht erkannt. Entschuldigung für den schlechten Rat.
quelle
Ich fand, dass das Festlegen der Annotation @Repository Spring in unseren DAOs und das Verwalten von EntityManager durch Spring und das Injizieren durch Annotation @PersistenceContext der bequemste Weg ist, um alles flüssig zum Laufen zu bringen. Sie profitieren von der Thread-Sicherheit des freigegebenen EntityManager und der Ausnahmeübersetzung. Standardmäßig verwaltet der gemeinsam genutzte EntityManager Transaktionen, wenn Sie beispielsweise mehrere DAOs eines Managers kombinieren. Am Ende werden Sie feststellen, dass Ihre DAOs anämisch werden.
quelle