Ich bin mir ziemlich sicher, dass Finalize immer noch schlechte Nachrichten über spätere JVMs ist-gibt es eine Alternative?

StackOverflow https://stackoverflow.com/questions/5359367

  •  27-10-2019
  •  | 
  •  

Frage

Ich möchte ein System im Orm-Stil implementieren, das Updates für Pojos speichern kann, wenn sie vom Anrufer nicht mehr erreichbar sind.

Ich dachte Null.

Ich könnte einen Finalizer verwenden, aber das letzte Mal, als ich diese überprüft habe, waren er fraglich (nicht garantiert, dass sie sofort ausgeführt oder überhaupt ausgeführt werden)-ich glaube, eine Kombination von Finalizern und Runshutdownhook () würde funktionieren, aber das wird in ein ziemlich sumpfiges Gebiet.

Gibt es einen anderen Weg, den ich nicht als an den obligatorischen "einfach den Anrufer rufen" .Save () nach, wenn er fertig ist? "

War es hilfreich?

Lösung

Versuchen Sie nur, es zu vermeiden, anrufen zu müssen save() Bei jedem Pojo, das Sie ändern?

Dies kann zuverlässig mit einem Persistenzsitzungsobjekt wie folgt erfolgen:

  1. Öffnen Sie ein neues Sitzungsobjekt.
  2. Laden Sie Objekte über das Sitzungsobjekt. Das Sitzungsobjekt verwaltet Verweise auf alle Objekte, die es lädt.
  3. Nehmen Sie Änderungen an den geladenen Objekten vor. Es ist nicht erforderlich, eine Speichermethode für aktualisierte Objekte aufzurufen.
  4. Schließen Sie das Sitzungsobjekt. Die Sitzung rettet alle ihre Objekte. Es könnte sogar ausgefallen genug sein, eine Kopie von sauber geladenen Daten zu behalten, alle Objekte mit den sauberen Daten zu vergleichen und nur die geändert zu speichern.

Und wenn Sie keine Sitzungsobjekte über Ihren Code übergeben möchten, können Sie die Dinge noch einen Schritt weiter mit der Arbeitseinheit gehen und ein Sitzungsobjekt mit dem aktuellen Thread assoziieren:

  1. Starten Sie eine Arbeitseinheit. Dadurch werden hinter den Kulissen ein Sitzungsobjekt erstellt und es mit dem aktuellen Thread assoziiert.
  2. Objekte laden. Wenn ein Objekt geladen wird, verbindet Ihr ORM es automatisch mit einem Sitzungsobjekt basierend auf dem aktuellen Thread.
  3. Nehmen Sie Änderungen an den geladenen Objekten vor. Es ist nicht erforderlich, eine Speichermethode für aktualisierte Objekte aufzurufen.
  4. Vervollständigen Sie die Arbeitseinheit. Dies schließt das Sitzungsobjekt und speichert alle Objekte.

Dies behebt mehrere Probleme mit einer leistungsbasierten Lösung:

  • Sie verlassen sich nicht auf nicht deterministische Müllsammlungen, die möglicherweise eine lange Zeit zwischen Läufen oder überhaupt nicht laufen.
  • Alle in einer Operation geänderten Objekte werden zusammen gespeichert. Wenn Sie sich auf die Erreichbarkeit verlassen, können verschiedene Objekte zu unterschiedlichen Zeiten nicht erreichbar werden, was bedeutet, dass Ihre Änderungen in Bit-and-Stickes in der Datenbank gespeichert werden können.
  • Rollback ist viel einfacher - geben Sie Ihrem Sitzungsobjekt einfach eine Rollback () -Methode. Mit einer Erreichbarkeitslösung müssen Sie sich daran erinnern, Rollback () bei jedem geänderten Pojo aufzurufen, wenn eine Operation ausfällt, was wirklich mit Ihrem ursprünglichen Problem gleich ist.

Vielleicht sehen http://nhibernate.info/doc/patternsandPractices/nhibernate-and-unit-of-work-pattern.html Oder recherchieren Sie die Einheit des Arbeitsmusters und emulieren einige dieser Ideen.

Andere Tipps

Verwenden Sie das Beobachtermuster. Erstellen Sie einen Clearancemanager und einige Zerstörungen. Identisch ist eine Schnittstelle, die für die Beobachter verwendet wird, die die Methode öffentlich Void Destroy () Der Clearancemanager enthält, ist Gegenstand der Beobachtermüßer. Verwenden Sie vielleicht Singleton hier, um sicherzustellen, dass Sie nur ein Clearancemanager -Objekt in Ihrer Anwendung haben.

Verwenden Sie ein Set in Internal im Clearancemanager (keine Liste, um sicherzustellen, dass Objekte nur einmal hinzugefügt werden können)

Unterstützen Sie eine adddestroyable (identorbare destorienfähige) Methode (und möglicherweise eine entfernte ausführliche).

Während der Laufzeit können die Klassen, für die Sie eine Destruktor -Emulation benötigen, sie selbst im Clearencemanager registrieren. Clearencemanager.getInstance (). AddDestroyable (this);

Der Clearancemanager hat eine Methode von Doclearance (), die nur am Ende der Hauptmethode aufgerufen werden sollte. Es warf das private Set und ruft Destroy () auf jedes identische Objekt auf.

Wenn Sie dies so tun, können Sie Destruktoren nachahmen, ohne sie zu verwenden, denn mit Destruktoren verlieren Sie die Kontrolle über die Existenz von Myabe benötigte Objekt. Sie wissen nicht, wenn Sie die Finalisierung überschreiben, wenn es aufgerufen wird.

Wenn Sie in Ihrer Hauptmethode nicht doclearance () nicht anrufen möchten, können Sie hier nicht anrufen, sondern nur hier, ein echter Destructor Finalize (). Da es im Clearencemanager auf die erforderlichen Objekte Referenzen gibt, werden sie nicht zuerst zerstört. Aber vielleicht mhh, wenn es Kreuzreferenzen gibt .... Besser nicht endgültig, verwenden Sie Doclearance () und haben Sie Spaß damit :)

Ich denke, Sie bellen hier den falschen Baum.

Alle Java -Finalizer- und Referenzmechanismen, die auf der Erreichbarkeit basieren, hängen von dem Müllsammler ab, um festzustellen, ob die jeweiligen Objekte erreichbar sind. Wenn Sie also einen der Referenzmechanismen für eine Art von Abschluss verwenden, stoßen Sie auf die gleichen Probleme, die darstellen finalize eine schlechte Idee.

Es ist technisch gesehen möglich, Ihre eigenen Mechanismen zur Erreichbarkeit zu implementieren. EG durch Implementierung Ihrer eigenen anwendungsspezifischen Referenzzählung. Es ist jedoch wahrscheinlich teuer, zerbrechlich und macht Ihren Code schrecklich. (Referenzzählung in Java ist wahrscheinlich unordentlicher und zerbrechlicher als in C ++, da Sie Referenzzuweisungsbetreiber nicht überlasteten, um sicherzustellen, dass die Referenzzahlen transparent angepasst werden. Daher muss jede Referenzzuweisung in einen Methodenaufruf eingewickelt werden.) Ich würde sagen, dass eine eigene Erreichbarkeitsanalyse a ist schlechte Idee.

Um praktisch zu sein, brauchen Sie also:

  • Überdenken Sie Ihr Design, damit Sie keine Dinge basierend auf der Erreichbarkeit tun, oder
  • Lebe mit den Konsequenzen der Verwendung von Finalize.

Die erste Option ist eindeutig die beste, IMO.

Vielleicht können Sie Phantomreferenz unterklassen und die erforderlichen Daten für endgültige Aktionen speichern.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top