Ich habe lange Zeit ein kompliziertes Überprüfungssystem implementiert, um Datenbanktransaktionen verwenden zu können. Die Transaktionslogik lautet wie folgt: Öffnen Sie eine Transaktion, führen Sie die Datenbankoperationen aus, führen Sie ein Rollback bei einem Fehler durch oder schreiben Sie bei Erfolg fest. Die Komplikation ergibt sich aus dem, was passiert, wenn eine zusätzliche Operation innerhalb derselben Transaktion ausgeführt werden soll. Sie müssten entweder eine zweite Methode vollständig schreiben, die beide Operationen ausführt, oder Sie könnten Ihre ursprüngliche Methode von einer Sekunde an aufrufen, indem Sie eine Transaktion nur öffnen, wenn noch keine geöffnet wurde, und Änderungen nur dann festschreiben / zurücksetzen, wenn Sie die waren eine, um die Transaktion zu öffnen.
Zum Beispiel:
public void method1() {
boolean selfOpened = false;
if(!transaction.isOpen()) {
selfOpened = true;
transaction.open();
}
try {
performDbOperations();
method2();
if(selfOpened)
transaction.commit();
} catch (SQLException e) {
if(selfOpened)
transaction.rollback();
throw e;
}
}
public void method2() {
boolean selfOpened = false;
if(!transaction.isOpen()) {
selfOpened = true;
transaction.open();
}
try {
performMoreDbOperations();
if(selfOpened)
transaction.commit();
} catch (SQLException e) {
if(selfOpened)
transaction.rollback();
throw e;
}
}
Bitte beachten Sie, dass ich den obigen Code in keiner Weise befürworte. Dies sollte als Beispiel dafür dienen, was nicht zu tun ist!
Es schien albern, eine zweite Methode zu erstellen, um die gleiche Logik wie die erste und etwas Besonderes auszuführen, aber ich wollte in der Lage sein, den Datenbank-API-Abschnitt des Programms aufzurufen und dort Probleme abzudichten. Während dies mein Problem teilweise löste, umfasste jede Methode, die ich schrieb, das Hinzufügen dieser ausführlichen Logik zum Überprüfen, ob eine Transaktion bereits geöffnet ist, und das Festschreiben / Zurücksetzen von Änderungen, wenn meine Methode sie geöffnet hat.
Das Problem war konzeptionell. Ich hätte nicht versuchen sollen, jedes mögliche Szenario anzunehmen. Der richtige Ansatz bestand darin, die Transaktionslogik in einer einzigen Methode unterzubringen, wobei eine zweite Methode als Parameter verwendet wurde, der die eigentliche Datenbanklogik ausführen würde. Diese Logik setzt voraus, dass die Transaktion offen ist und führt nicht einmal eine Prüfung durch. Diese Methoden können in Kombination aufgerufen werden, damit diese Methoden nicht mit unnötiger Transaktionslogik überfüllt sind.
Der Grund, warum ich dies erwähne, ist, dass mein Fehler darin bestand anzunehmen, dass ich meine Methode in jeder Situation zum Laufen bringen musste. Dabei überprüfte meine aufgerufene Methode nicht nur, ob eine Transaktion geöffnet war, sondern auch die von ihr aufgerufenen. In diesem Fall handelt es sich nicht um einen großen Leistungseinbruch, aber wenn ich beispielsweise das Vorhandensein eines Datensatzes in der Datenbank überprüfen müsste, bevor ich fortfahre, würde ich nach jeder Methode suchen, die dies erfordert, wenn ich dies nur hätte annehmen sollen Der Anrufer sollte darauf hingewiesen werden, dass der Datensatz vorhanden sein sollte. Wenn die Methode trotzdem aufgerufen wird, ist dies ein undefiniertes Verhalten, und Sie müssen sich keine Gedanken darüber machen, was passiert.
Vielmehr sollten Sie ausreichend Dokumentation bereitstellen und schreiben, was Sie für wahr halten, bevor Ihre Methode aufgerufen wird. Wenn es wichtig genug ist, fügen Sie es als Kommentar vor Ihrer Methode hinzu, damit es keinen Fehler gibt (javadoc bietet eine gute Unterstützung für diese Art von Dingen in Java).
Ich hoffe das hilft!