Czy można ustawić domyślną wartość dla kolumn w JPA, a jeśli tak, to jak to zrobić za pomocą adnotacji?
java
jpa
annotations
homaxto
źródło
źródło
Odpowiedzi:
W rzeczywistości jest to możliwe w JPA, choć trochę hack przy użyciu
columnDefinition
właściwości@Column
adnotacji, na przykład:źródło
insertable=false
jeśli kolumna ma wartość zerową (i aby uniknąć niepotrzebnego argumentu kolumny).Możesz wykonać następujące czynności:
Tam! Właśnie wykorzystałeś zero jako wartość domyślną.
Pamiętaj, że będzie ci to służyć, jeśli tylko uzyskujesz dostęp do bazy danych z tej aplikacji. Jeśli inne aplikacje również korzystają z bazy danych, należy to sprawdzić w bazie danych, używając atrybutu adnotacji columnDefinition Camerona lub w inny sposób.
źródło
Example
obiekt jako prototyp wyszukiwania. Po ustawieniu wartości domyślnej przykładowe zapytanie Hibernacja nie będzie już ignorowało skojarzonej kolumny, w której wcześniej ją ignorowało, ponieważ była pusta. Lepszym rozwiązaniem jest ustawienie wszystkich wartości domyślnych tuż przed wywołaniem hibernacjisave()
lubupdate()
. To lepiej naśladuje zachowanie bazy danych, która ustawia wartości domyślne podczas zapisywania wiersza.null
na przykład ustawienie ). Korzystanie@PrePersist
i@PreUpdate
jest lepszą opcją imho.columnDefinition
właściwość nie jest niezależna od bazy danych i@PrePersist
przesłania ustawienie przed wstawieniem, „wartość domyślna” to coś innego, wartość domyślna jest używana, gdy wartość nie jest jawnie ustawiona.innym podejściem jest użycie javax.persistence.PrePersist
źródło
if (createdt != null) createdt = new Date();
? W tej chwili zastąpi to wyraźnie określoną wartość, co sprawia, że tak naprawdę nie jest to domyślna wartość.if (createdt == null) createdt = new Date();
null
czek.W 2017 r. JPA 2.1 wciąż ma tylko tę,
@Column(columnDefinition='...')
do której wstawiono dosłowną definicję SQL kolumny. Co jest dość nieelastyczne i zmusza Cię do zadeklarowania innych aspektów, takich jak typ, zwężając pogląd implementacji JPA na ten temat.Hibernacja ma jednak:
Dwie uwagi na ten temat:
1) Nie bój się pójść niestandardowo. Pracując jako programista JBoss, widziałem całkiem sporo procesów specyfikacji. Specyfikacja jest w gruncie rzeczy punktem odniesienia dla dużych graczy w danej dziedzinie, którzy chcą się zobowiązać do wsparcia przez następną dekadę. Dotyczy to bezpieczeństwa, w przypadku wiadomości ORM nie ma różnicy (chociaż JPA obejmuje całkiem sporo). Moje doświadczenie jako programisty polega na tym, że w złożonej aplikacji wcześniej czy później będziesz potrzebować niestandardowego interfejsu API. I
@ColumnDefault
jest przykładem, gdy przeważa nad negatywnymi skutkami stosowania niestandardowego rozwiązania.2) Fajnie, jak wszyscy machają @PrePersist lub inicjatorem członka konstruktora. Ale to NIE to samo. Co powiesz na masowe aktualizacje SQL? Co powiesz na stwierdzenia, które nie ustawiają kolumny?
DEFAULT
ma swoją rolę i nie można jej zastąpić przez zainicjowanie członka klasy Java.źródło
JPA nie obsługuje tego i byłoby przydatne, gdyby tak było. Użycie columnDefinition jest specyficzne dla DB i w wielu przypadkach jest niedopuszczalne. ustawienie wartości domyślnej w klasie nie wystarczy, gdy pobierzesz rekord o wartości zerowej (co zwykle dzieje się, gdy ponownie uruchomisz stare testy DBUnit). To, co robię, to:
Auto-boxing Java bardzo w tym pomaga.
źródło
Widząc, jak natknąłem się na to od Google, próbując rozwiązać ten sam problem, po prostu wrzucę rozwiązanie, które przygotowałem, na wypadek, gdyby ktoś uznał to za przydatne.
Z mojego punktu widzenia jest naprawdę tylko 1 rozwiązanie tego problemu - @PrePersist. Jeśli zrobisz to w @PrePersist, musisz jednak sprawdzić, czy wartość została już ustawiona.
źródło
@PrePersist
wybrałbym przypadek użycia OP.@Column(columnDefinition=...)
nie wydaje się bardzo elegancki.Właśnie przetestowałem problem. Działa dobrze. Dzięki za podpowiedź.
O komentarzach:
Ten nie ustawia domyślnej wartości kolumny w bazie danych (oczywiście).
źródło
możesz użyć Java odzwierciedlają API:
Jest to powszechne:
źródło
Field[] fields = object.getClass().getDeclaredFields();
wfor()
pliku może być również w porządku. Dodaj takżefinal
do parametru / wychwycone wyjątki, ponieważ nie chceszobject
, aby przypadkowo je zmodyfikowano. Również dodać czek nanull
:if (null == object) { throw new NullPointerException("Parameter 'object' is null"); }
. Dzięki temuobject.getClass()
można bezpiecznie wywoływać i nie uruchamia komendyNPE
. Powodem jest unikanie błędów przez leniwych programistów. ;-)Używam
columnDefinition
i działa bardzo dobrzeźródło
Nie możesz tego zrobić z adnotacją w kolumnie. Myślę, że jedynym sposobem jest ustawienie wartości domyślnej podczas tworzenia obiektu. Być może domyślny konstruktor byłby właściwym miejscem do tego.
źródło
@Column
. I tęsknię też za ustawianymi komentarzami (zaczerpniętymi z doctag Java).W moim przypadku zmodyfikowałem kod źródłowy hibernacji, cóż, aby wprowadzić nową adnotację
@DefaultValue
:Cóż, jest to rozwiązanie tylko do hibernacji.
źródło
@Column(columnDefinition='...')
nie działa po ustawieniu domyślnego ograniczenia w bazie danych podczas wstawiania danych.insertable = false
i usunąćcolumnDefinition='...'
adnotację, a następnie baza danych automatycznie wstawi wartość domyślną z bazy danych.insertable = false
Hibernate / JPA, to zadziała.źródło
W moim przypadku, ponieważ użyłem tego pola jako LocalDateTime, jest to zalecane ze względu na niezależność dostawcy
źródło
Adnotacje JPA ani Hibernacja nie obsługują pojęcia domyślnej wartości kolumny. Aby obejść to ograniczenie, ustaw wszystkie wartości domyślne tuż przed wywołaniem stanu hibernacji
save()
lubupdate()
sesji. To ściśle jak to możliwe (poza Hibernacją ustawienie wartości domyślnych) naśladuje zachowanie bazy danych, która ustawia wartości domyślne, gdy zapisuje wiersz w tabeli.W przeciwieństwie do ustawiania wartości domyślnych w klasie modelu, jak sugeruje ta alternatywna odpowiedź , takie podejście zapewnia również, że zapytania o kryteria, które wykorzystują
Example
obiekt jako prototyp do wyszukiwania, będą działać tak jak poprzednio. Po ustawieniu domyślnej wartości atrybutu zerowalnego (takiego, który ma typ nieprymitywny) w klasie modelu, Hibernacja zapytanie po przykładzie nie będzie już ignorować powiązanej kolumny, w której poprzednio byłaby ignorowana, ponieważ była pusta.źródło
W JPA nie jest to możliwe.
Oto, co można zrobić z dopiskiem kolumna: http://java.sun.com/javaee/5/docs/api/javax/persistence/Column.html
źródło
Jeśli używasz podwójnego, możesz użyć następujących opcji:
Tak, jest to specyficzne dla db.
źródło
Możesz zdefiniować wartość domyślną w projektancie bazy danych lub podczas tworzenia tabeli. Na przykład w programie SQL Server można ustawić domyślną przechowalnię pola Data na (
getDate()
). Użyjinsertable=false
zgodnie z definicją w kolumnie. JPA nie określi tej kolumny na wstawkach, a baza danych wygeneruje dla ciebie wartość.źródło
Musisz
insertable=false
w sobie@Column
adnotację. JPA zignoruje tę kolumnę podczas wstawiania do bazy danych i zostanie użyta wartość domyślna.Zobacz ten link: http://mariemjabloun.blogspot.com/2014/03/resolved-set-database-default-value-in.html
źródło
nullable=false
nie powiedzie się zSqlException
:Caused by: java.sql.SQLException: Column 'opening_times_created' cannot be null
. Tutaj zapomniałem ustawić znacznik czasu „utworzony”openingTime.setOpeningCreated(new Date())
. To dobry sposób na zachowanie spójności, ale o to pytający nie pytał.