Hibernate @NotNull vs @Column (nullable = false)

1. Úvod

Na prvý pohľad, môže sa zdať, že oboje @NotNull a @Column (nullable = false) anotácie slúžia rovnakému účelu a dajú sa zameniť. Ako však čoskoro uvidíme, nie je to celkom pravda.

Aj keď sa pri použití na entite JPA oba zásadne bránia skladovaniu nulový hodnoty v podkladovej databáze, existujú značné rozdiely medzi týmito dvoma prístupmi.

V tomto rýchlom návode porovnáme @NotNull a @Column (nullable = false) obmedzenia.

2. Závislosti

Pre všetky prezentované príklady použijeme jednoduchú aplikáciu Spring Boot.

Tu je relevantná časť dokumentu pom.xml súbor, ktorý zobrazuje potrebné závislosti:

  org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-validácia com.h2database h2 

2.1. Vzorová entita

Poďme tiež definovať veľmi jednoduchú entitu, ktorú budeme používať v celom tomto výučbe:

@Entity public class Item {@Id @GeneratedValue private Long id; súkromná cena BigDecimal; }

3. The @NotNull Anotácia

The @NotNull anotácia je definovaná v špecifikácii overenia fazule. To znamená, že jeho použitie nie je obmedzené iba na entity. Naopak, môžeme použiť @NotNull aj na ktorejkoľvek inej fazuli.

Zostaňme však pri našom prípade použitia a pridajme @NotNull anotácia k Položka‘S cena lúka:

@Entity public class Item {@Id @GeneratedValue private Long id; @NotNull súkromná cena BigDecimal; }

Skúsme teraz položku uchovať pomocou a nulovýcena:

@SpringBootTest verejná trieda ItemIntegrationTest {@Autowired private ItemRepository itemRepository; @Test public void shouldNotAllowToPersistNullItemsPrice () {itemRepository.save (new Item ()); }}

A pozrime sa na výstup z režimu dlhodobého spánku:

2019-11-14 12:31: 15.070 CHYBA 10980 --- [hlavný] ohiExceptionMapperStandardImpl: HHH000346: Chyba počas spravovaného vyprázdňovania [Overenie zlyhalo pre triedy [com.baeldung.h2db.springboot.models.Item] počas doby trvania pre skupiny [javax.validation.groups.Default,] Zoznam porušení obmedzenia: [ConstraintViolationImpl {interpolatedMessage = 'must be null', propertyPath = price, rootBeanClass = class com.baeldung.h2db.springboot.models.Item, messageTemplate = "{ javax.validation.constraints.NotNull.message} "}]] (...) Spôsobené: javax.validation.ConstraintViolationException: Overenie zlyhalo pre triedy [com.baeldung.h2db.springboot.models.Item] počas obdobia pretrvávania pre skupiny [javax.validation.groups.Default,] Zoznam porušení obmedzenia: [ConstraintViolationImpl {interpolatedMessage = 'must not null', propertyPath = price, rootBeanClass = class com.baeldung.h2db.springboot.models.Item, messageTemplate = "{ javax.validation.constraints.NotNull.message} "}]

Ako vidíme, v tomto prípade náš systém vyhodil javax.validation.ConstraintViolationException.

Je dôležité si uvedomiť, že režim dlhodobého spánku nespustil príkaz vloženia SQL. V dôsledku toho sa neplatné údaje neuložili do databázy.

Je to preto, že udalosť životného cyklu pre-pretrvávajúcej entity spustila validáciu fazule tesne pred odoslaním dotazu do databázy.

3.1. Generovanie schémy

V predchádzajúcej časti sme si predstavili, ako @NotNull overovacie práce.

Poďme teraz zistiť, čo sa stane, ak nechajte režim dlhodobého spánku vygenerovať nám databázovú schému.

Z tohto dôvodu nastavíme niekoľko vlastností v našom application.properties spis:

spring.jpa.hibernate.ddl-auto = create-drop spring.jpa.show-sql = true

Ak teraz spustíme našu aplikáciu, zobrazí sa nám vyhlásenie DDL:

vytvoriť položku tabuľky (id bigint nie null, cena desatinná (19,2) nie null, primárny kľúč (id))

Prekvapivo Hibernácia automaticky pridáva nie null obmedzenie cena definícia stĺpca.

Ako je to možné?

Ukázalo sa, že, po vybalení z režimu dlhodobého spánku preloží hibernácia poznámky o overení fazule použité na entity do metadát schémy DDL.

To je celkom pohodlné a dáva to veľký zmysel. Ak podáme žiadosť @NotNull k entite, s najväčšou pravdepodobnosťou chceme vytvoriť zodpovedajúci databázový stĺpec nie null tiež.

Ak však z nejakého dôvodu chceme Ak chcete túto funkciu dlhodobého spánku deaktivovať, je potrebné iba nastaviť hibernate.validator.apply_to_ddl majetok do nepravdivé.

Aby sme to otestovali, aktualizujme naše application.properties:

spring.jpa.hibernate.ddl-auto = create-drop spring.jpa.show-sql = true spring.jpa.properties.hibernate.validator.apply_to_ddl = false

Spustíme aplikáciu a pozrieme si vyhlásenie DDL:

vytvoriť položku tabuľky (id bigint nie null, cena desatinná (19,2), primárny kľúč (id))

Podľa očakávania, tentokrát Hibernate nepridal nie null obmedzenie cena stĺpec.

4. The @Column (nullable = false) Anotácia

The @ Stĺpec anotácia je definovaná ako súčasť špecifikácie API Java Persistence.

Používa sa hlavne pri generovaní metadát schémy DDL. To znamená, že ak necháme Hibernate generovať databázovú schému automaticky, použije sa nie null obmedzenia konkrétneho databázového stĺpca.

Aktualizujme naše Položka subjekt s @Column (nullable = false) a uvidíte, ako to funguje v praxi:

@Entity public class Item {@Id @GeneratedValue private Long id; @Column (nullable = false) súkromná cena BigDecimal; }

Teraz sa môžeme pokúsiť vytrvať a nulová cena hodnota:

@SpringBootTest verejná trieda ItemIntegrationTest {@Autowired private ItemRepository itemRepository; @Test public void shouldNotAllowToPersistNullItemsPrice () {itemRepository.save (new Item ()); }}

Tu je úryvok výstupu z režimu dlhodobého spánku:

Hibernácia: vytvorenie položky tabuľky (id bigint nie null, cena desatinná (19,2) null, primárny kľúč (id)) (...) Hibernácia: vloženie do hodnoty položky (cena, id) (?,?) 2019- 11-14 13: 23: 03.000 UPOZORNENIE 14580 --- [hlavný] ohengine.jdbc.spi.SqlExceptionHelper: Chyba SQL: 23502, SQLState: 23502 2019-11-14 13: 23: 03.000 CHYBA 14580 --- [hlavný ] ohengine.jdbc.spi.SqlExceptionHelper: NULL nie je povolené pre stĺpec "PRICE"

V prvom rade si to môžeme všimnúť Hibernácia vygenerovala stĺpec ceny s nie null obmedzenie, ako sme predpokladali.

Ďalej bola schopná vytvoriť vložený dotaz SQL a odovzdať ho. Ako výsledok, je to podkladová databáza, ktorá spustila chybu.

4.1. Validácia

Zdôrazňujú to takmer všetky zdroje @Column (nullable = false) sa používa iba na generovanie schémy DDL.

Hibernácia je však schopná vykonať validáciu subjektu proti možnému nulový hodnoty, aj keď je príslušné pole anotované iba pomocou @Column (nullable = false).

Ak chcete aktivovať túto funkciu dlhodobého spánku, musíme explicitne nastaviť hibernate.check_nullability majetok do pravda:

spring.jpa.show-sql = true spring.jpa.properties.hibernate.check_nullability = true

Poďme teraz znova vykonať náš testovací prípad a preskúmať výstup:

org.springframework.dao.DataIntegrityViolationException: vlastnosť nenulová odkazuje na nulovú alebo prechodnú hodnotu: com.baeldung.h2db.springboot.models.Item.price; vnorenou výnimkou je org.hibernate.PropertyValueException: vlastnosť nenulová odkazuje na nulovú alebo prechodnú hodnotu: com.baeldung.h2db.springboot.models.Item.price

Tentokrát náš testovací prípad vyhodil org.hibernate.PropertyValueException.

Je nevyhnutné si všimnúť, že v tomto prípade Hibernate neposlal vložený dotaz SQL do databázy.

5. Zhrnutie

V tomto článku sme opísali, ako @NotNull a @Column (s možnou hodnotou null - false) anotácie fungujú.

Napriek tomu, že obidve nám bránia v ukladaní nulový hodnoty v databáze, uplatňujú rôzne prístupy.

Ako pravidlo, mali by sme uprednostniť @NotNull anotácia nad @Column (nullable = false) anotácia. Týmto spôsobom zaistíme, aby overenie prebehlo skôr, ako Hibernate odošle do databázy akékoľvek dotazy týkajúce sa vloženia alebo aktualizácie.

Tiež je to zvyčajne radšej sa spoľahnite na štandardné pravidlá definované v Bean Validation, namiesto toho, aby sme nechali databázu spracovať validačnú logiku.

Ale aj keď necháme Hibernate vygenerovať databázovú schému, preloží sa @NotNull anotácie do databázových obmedzení. Musíme sa potom iba ubezpečiť, že hibernate.validator.apply_to_ddl vlastnosť je nastavená na pravda.

Ako obvykle sú všetky príklady kódov k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found