Logik: Datenbank oder Anwendung / 2 (Einschränkungen überprüfen)
-
03-07-2019 - |
Frage
Dies ist eine spezielle Version von href="https://stackoverflow.com/questions/119540/business-logic-database-or-application-layer">.
Ich möchte überprüfen, ob ich eine doppelte Zeile bin einfügen. Soll ich es programmatisch in meiner Anwendungsschicht überprüfen:
if (exists(obj))
{
throw new DuplicateObjectException();
}
HibernateSessionFactory.getSession().save(obj);
oder sollte ich fangen die durch die Datenbankschicht geworfen Ausnahme ausgelöst wird, sobald ich die contraint verletzen?
try
{
HibernateSessionFactory.getSession().save(obj);
}
catch(ConstraintViolationException e)
{
throw new DuplicateObjectException();
}
EDIT: Mit anderen Worten: wenn die Einschränkung gibt es zu bleiben (es ist gut, Datenbank-Design wie auch immer, und ich kann meine app wird die einzige Zugriff auf die Tabelle nicht sicher sein) werde ich verlassen sich auf die Einschränkung und behandeln die Ausnahme seiner Verletzung erhöhen wird, oder ich würde besser überprüfen eigentlich?
EDIT2: Natürlich I + innerhalb einer Transaktion einfügen prüfe, die Tabellensperren kein anderer Prozess, um sicherzustellen, einen anderen Datensatz in der Zwischenzeit das Schreiben
Lösung
Zuerst Sie muss einen Primärschlüssel oder eindeutige Einschränkung auf die Datenbank haben diese Einzigartigkeit richtig zu erzwingen -. Keine Frage
Da der Zwang besteht, die Art und Weise sollten Sie in der Anwendung Code? Meine Präferenz wäre, den Einsatz zu versuchen und die Ausnahmen zu fangen. Da vermutlich die meisten Einsätze erfolgreich zu sein, nur wenige werden nicht als Duplikate (das ist, was „Ausnahme“ bedeutet!): Es ineffizient ist vor jedem Einsatz eine existiert Prüfung durchzuführen, wenn die Datenbank eine eigene Einschränkung wird sich aufführen Überprüfung sowieso.
Auch ist es theoretisch möglich, dass das falsch sowieso sein existiert überprüfen - wenn jemand anderes einen Datensatz mit dem gleichen Schlüsselwert in dem kleinen Intervall zu begehen verwaltet zwischen Ihrem Scheck und Ihrem Einsatz vorhanden ist. Dann, wenn Sie die Datenbank Ausnahme nicht abfangen zu tun, glauben Sie der Einsatz gelang es, wenn in der Tat ist es nicht.
Andere Tipps
Sie überprüfen, dass das Objekt nur in Anwendungscode vorhanden ist, und dann einmal davon überzeugt, dass es nicht, ungeniert das Objekt speichern. Aber ein andere gleichzeitige Client kann ihr eigenes Objekt im Moment zwischen den beiden Codezeilen einzufügen. So dass Sie auf jeden Fall eine doppelte Ausnahme bekommen würde, nur dieses Mal, wenn Sie es nicht fangen.
Sie müssen die Speicher tun () und die Ausnahme abfangen. Ansonsten haben Sie eine Race Condition mit anderen Clients gleichzeitig auf der gleichen Datenbank arbeiten.
Sie müssen die Datenbank Ausnahme fangen, wenn Sie garantieren können, dass Ihre Anwendung die einzige ist, die jemals fügt Zeilen (und immer Reihen fügt) in Ihrer Datenbank.
EDIT: Ich kann die Frage falsch verstanden, aber ich würde immer noch argumentieren, dass die Option B (HibernateSessionFactory führt die ConstraintException aus der Datenbank) ist die bessere Option. Es gibt immer eine kleine Chance, dass ein andere Anwendung etwas in dem Zeitsplitter zwischen dem Check und dem eigentlichen Funktionsaufruf einfügen könnte. Darüber hinaus ist der einzige Weg für eine Betrogene überprüfen eine zusätzliche Abfrage auszuführen, die nur eine unnötige Belastung für die Leistung ist.
Mein ursprüngliches Verständnis der Frage war die in Option A würde die Betrogene Prüfung intern durchgeführt werden (das heißt, indem nur die Datenstrukturen, die das Programm bereits geschaffen hatte, und ohne Abfrage, bis die INSERT). Meine ursprüngliche Antwort war als Antwort auf diese Methode.
Im Allgemeinen versuche ich Codierung zu vermeiden, die auf Fehler geworfen beruht, weil ich etwas falsch gemacht haben. Manchmal aber ist das alles, was Sie tun können. In Ihrer Situation, ich glaube, Sie sollten zuerst überprüfen.
Dies wird brechen (so dass doppelte Einträge), wenn die Einschränkung aus irgendeinem Grund fallen gelassen wird (in der Regel Wartungsarbeiten, wo der DBA es wieder aktivieren vernachlässigt). Sie sollten in der Anwendung für diese Situation überprüfen.
Allerdings ist es eine gute Datenbank-Design der Datenbank erzwingen die Einschränkung haben (wie Sie haben zu Recht darauf hingewiesen), wie andere auch die Datenbank verwenden können. Als Verallgemeinerung ist es am besten zu der Annahme, dass die Anwendungen und Datenbanken in einer M leben. M Beziehung - das wird der Fall sein, fast die ganze Zeit
Die Ausnahmen von Hibernate (oder jeder ORM-Komponente) geworfen neigen dazu, schwer zu interpretieren zu sein.
Wenn die Ausnahme genügend Informationen hat, dass Sie eine Fehlermeldung erzeugen kann, die tatsächlich dem Benutzer hilft, dann nur die Ausnahme abfangen, analysieren und weitergehen.
Wenn die Ausnahme nicht genügend Informationen hat, dann haben Sie für den Fehlerzustand zu überprüfen, und erzeugen eine hilfreiche Fehlermeldung an den Benutzer, dass sie etwas falsch zu machen sind.
Die Frage ist eine der „wie undurchsichtig ist die Ausnahme“? Einige sind ziemlich undurchsichtig. Andere haben genug, dass Sie die Nachrichtenzeichenfolge analysieren können und herauszufinden, was für den Benutzer zu sagen.
Sobald Hibernate löst eine Ausnahme aus der Sitzung verwerfen müssen die Sitzung (siehe Abschnitt 11.2.3). Also, wenn Sie für dups überprüfen müssen und weiterhin die gleiche Sitzung verwenden, dann haben Sie keine andere Wahl, als erste in der Anwendung zu überprüfen.
Auch besteht die Möglichkeit, mit dem Code in dem ersten Schnipsel, dass ein anderer Prozess ein Datensatz einfügen könnte, dass die doppelte Ausnahme zwischen der Zeit geworfen werden verursachen würden Sie für den doppelten Datensatz überprüfen und die Zeit, es wird tatsächlich eingefügt.