Ist es möglich, einen Standardwert für Spalten in JPA festzulegen, und wenn ja, wie erfolgt dies mithilfe von Anmerkungen?
java
jpa
annotations
homaxto
quelle
quelle
Antworten:
Tatsächlich ist es in JPA möglich, obwohl ein kleiner Hack die
columnDefinition
Eigenschaft der@Column
Annotation verwendet, zum Beispiel:quelle
insertable=false
wenn die Spalte nullwertfähig ist (und um das nicht benötigte Spaltenargument zu vermeiden).Sie können Folgendes tun:
Dort! Sie haben gerade Null als Standardwert verwendet.
Beachten Sie, dass dies nur dann von Nutzen ist, wenn Sie nur über diese Anwendung auf die Datenbank zugreifen. Wenn andere Anwendungen die Datenbank ebenfalls verwenden, sollten Sie diese Prüfung in der Datenbank mithilfe des Annotation-Attributs columnDefinition von Cameron oder auf andere Weise durchführen.
quelle
Example
Objekt als Prototyp für die Suche verwenden. Nach dem Festlegen eines Standardwerts ignoriert eine Beispielabfrage im Ruhezustand die zugeordnete Spalte nicht mehr, wo sie zuvor ignoriert wurde, weil sie null war. Ein besserer Ansatz besteht darin, alle Standardwerte unmittelbar vor dem Aufrufen eines Ruhezustandssave()
oder festzulegenupdate()
. Dies ahmt das Verhalten der Datenbank besser nach, die beim Speichern einer Zeile Standardwerte festlegt.null
z. B. Einstellung ). Verwenden@PrePersist
und@PreUpdate
ist eine bessere Option imho.columnDefinition
Die Eigenschaft ist nicht datenbankunabhängig und@PrePersist
überschreibt Ihre Einstellung vor dem Einfügen. "Standardwert" ist etwas anderes. Der Standardwert wird verwendet, wenn der Wert nicht explizit festgelegt wird.Ein anderer Ansatz ist die Verwendung von javax.persistence.PrePersist
quelle
if (createdt != null) createdt = new Date();
oder so? Im Moment wird dadurch ein explizit angegebener Wert überschrieben, was dazu führt, dass er nicht wirklich ein Standardwert ist.if (createdt == null) createdt = new Date();
null
Scheck hinzugefügt .Im Jahr 2017 hat JPA 2.1 nur noch das,
@Column(columnDefinition='...')
in das Sie die wörtliche SQL-Definition der Spalte einfügen. Das ist ziemlich unflexibel und zwingt Sie, auch die anderen Aspekte wie Typ zu deklarieren, wodurch die Ansicht der JPA-Implementierung in dieser Angelegenheit kurzgeschlossen wird.Hibernate hat jedoch Folgendes:
Zwei Anmerkungen dazu:
1) Haben Sie keine Angst davor, nicht dem Standard zu entsprechen. Als JBoss-Entwickler habe ich einige Spezifikationsprozesse gesehen. Die Spezifikation ist im Grunde die Basis, die die großen Akteure in einem bestimmten Bereich bereit sind, sich für das nächste Jahrzehnt oder so zur Unterstützung zu verpflichten. Es ist wahr für die Sicherheit, für Messaging, ORM ist kein Unterschied (obwohl JPA ziemlich viel abdeckt). Meine Erfahrung als Entwickler zeigt, dass Sie in einer komplexen Anwendung früher oder später ohnehin eine nicht standardmäßige API benötigen. Und
@ColumnDefault
ist ein Beispiel, wenn es die Nachteile einer nicht standardmäßigen Lösung überwiegt.2) Es ist schön, wie jeder die Initialisierung von @PrePersist oder Konstruktormitgliedern winkt. Aber das ist NICHT dasselbe. Wie wäre es mit Massen-SQL-Updates? Wie wäre es mit Anweisungen, die die Spalte nicht setzen?
DEFAULT
hat seine Rolle und kann nicht durch Initialisieren eines Java-Klassenmitglieds ersetzt werden.quelle
JPA unterstützt das nicht und es wäre nützlich, wenn es dies tun würde. Die Verwendung von columnDefinition ist DB-spezifisch und in vielen Fällen nicht akzeptabel. Das Festlegen eines Standardwerts in der Klasse reicht nicht aus, wenn Sie einen Datensatz mit Nullwerten abrufen (was normalerweise passiert, wenn Sie alte DBUnit-Tests erneut ausführen). Was ich tue ist folgendes:
Java Auto-Boxing hilft dabei sehr.
quelle
Da ich bei dem Versuch, das gleiche Problem zu lösen, auf Google gestoßen bin, werde ich nur die Lösung einwerfen, die ich mir ausgedacht habe, falls jemand sie nützlich findet.
Aus meiner Sicht gibt es wirklich nur 1 Lösung für dieses Problem - @PrePersist. Wenn Sie dies in @PrePersist tun, müssen Sie überprüfen, ob der Wert bereits festgelegt wurde.
quelle
@PrePersist
von OP entscheiden.@Column(columnDefinition=...)
scheint nicht sehr elegant.Ich habe das Problem gerade getestet. Es funktioniert gut. Danke für den Tipp.
Über die Kommentare:
Dieser legt (natürlich) nicht den Standardspaltenwert in der Datenbank fest.
quelle
Sie können die Java Reflect API verwenden:
Das ist üblich:
quelle
Field[] fields = object.getClass().getDeclaredFields();
infor()
einzufügen. Fügenfinal
Sie außerdem Parameter / abgefangene Ausnahmen hinzu, da Sie nicht versehentlichobject
geändert werden möchten . Fügen Sie auch eine Überprüfung hinzunull
:if (null == object) { throw new NullPointerException("Parameter 'object' is null"); }
. Das stellt sicher, dassobject.getClass()
das Aufrufen sicher ist und kein a auslöstNPE
. Der Grund ist, Fehler von faulen Programmierern zu vermeiden. ;-)Ich benutze
columnDefinition
und es funktioniert sehr gutquelle
Sie können dies nicht mit der Spaltenanmerkung tun. Ich denke, die einzige Möglichkeit besteht darin, den Standardwert festzulegen, wenn ein Objekt erstellt wird. Vielleicht wäre der Standardkonstruktor der richtige Ort dafür.
quelle
@Column
around. Und ich vermisse es auch, Kommentare zu setzen (entnommen aus Java doctag).In meinem Fall habe ich den Quellcode des Ruhezustands geändert, um eine neue Anmerkung einzuführen
@DefaultValue
:Nun, dies ist eine Lösung nur für den Ruhezustand.
quelle
@Column(columnDefinition='...')
funktioniert nicht, wenn Sie beim Einfügen der Daten die Standardeinschränkung in der Datenbank festlegen.insertable = false
und aus dieser entfernencolumnDefinition='...'
, dann fügt die Datenbank automatisch den Standardwert aus der Datenbank ein.insertable = false
Hibernate / JPA hinzufügen , es wird funktionieren.quelle
In meinem Fall wird dies aufgrund der Unabhängigkeit des Anbieters empfohlen, da das Feld LocalDateTime verwendet wird
quelle
Weder JPA- noch Hibernate-Annotationen unterstützen den Begriff eines Standardspaltenwerts. Um dieses Problem zu umgehen, legen Sie alle Standardwerte fest, bevor Sie einen Ruhezustand aufrufen
save()
oderupdate()
die Sitzung . Dies ahmt das Verhalten der Datenbank nach, die beim Speichern einer Zeile in einer Tabelle Standardwerte festlegt (kurz bevor der Ruhezustand die Standardwerte festlegt).Im Gegensatz zum Festlegen der Standardwerte in der Modellklasse, wie diese alternative Antwort vorschlägt, stellt dieser Ansatz auch sicher, dass Kriterienabfragen, die ein
Example
Objekt als Prototyp für die Suche verwenden, weiterhin wie zuvor funktionieren. Wenn Sie den Standardwert eines nullfähigen Attributs (eines Attributs mit einem nicht primitiven Typ) in einer Modellklasse festlegen, ignoriert eine Beispielabfrage im Ruhezustand die zugeordnete Spalte nicht mehr, wo sie zuvor ignoriert wurde, weil sie null war.quelle
Dies ist in JPA nicht möglich.
Mit der Spaltenanmerkung können Sie Folgendes tun: http://java.sun.com/javaee/5/docs/api/javax/persistence/Column.html
quelle
Wenn Sie ein Double verwenden, können Sie Folgendes verwenden:
Ja, es ist db-spezifisch.
quelle
Sie können den Standardwert im Datenbankdesigner oder beim Erstellen der Tabelle definieren. In SQL Server können Sie beispielsweise den Standard-Tresor eines Datumsfelds auf (
getDate()
) setzen. Verwenden Sie dieseinsertable=false
wie in Ihrer Spaltendefinition angegeben. JPA gibt diese Spalte in Einfügungen nicht an und die Datenbank generiert den Wert für Sie.quelle
Sie müssen
insertable=false
in Ihrer@Column
Anmerkung. JPA ignoriert dann diese Spalte beim Einfügen in die Datenbank und der Standardwert wird verwendet.Siehe diesen Link: http://mariemjabloun.blogspot.com/2014/03/resolved-set-database-default-value-in.html
quelle
nullable=false
wird mit einem scheiternSqlException
:Caused by: java.sql.SQLException: Column 'opening_times_created' cannot be null
. Hier habe ich vergessen, den "erstellten" Zeitstempel mit zu setzenopeningTime.setOpeningCreated(new Date())
. Dies ist eine gute Art, Konsistenz zu haben, aber das hat der Fragesteller nicht gefragt.