Kebingungan: @NotNull vs. @Column (nullable = false) dengan JPA dan Hibernate

242
  1. Ketika mereka muncul di bidang / pengambil sebuah @Entity, apa perbedaan di antara mereka? (Saya bertahan Entitas melalui Hibernate ).

  2. Kerangka kerja dan / atau spesifikasi apa yang dimiliki masing-masing?

  3. @NotNullterletak di dalam javax.validation.constraints. Di javax.validation.constraints.NotNulljavadoc dikatakan

    Elemen beranotasi tidak boleh nol

    tetapi tidak berbicara tentang representasi elemen dalam database, jadi mengapa saya menambahkan kendala nullable=falseke kolom?

penuh
sumber

Jawaban:

328

@NotNulladalah anotasi Validasi Bean JSR 303 . Itu tidak ada hubungannya dengan kendala database itu sendiri. Karena Hibernate adalah implementasi referensi dari JSR 303, bagaimanapun, ia secara cerdas mengambil kendala-kendala ini dan menerjemahkannya ke dalam kendala basis data untuk Anda, sehingga Anda mendapatkan dua untuk harga satu. @Column(nullable = false)adalah cara JPA untuk mendeklarasikan kolom sebagai bukan-nol. Yaitu yang pertama dimaksudkan untuk validasi dan yang terakhir untuk menunjukkan rincian skema database. Anda hanya mendapatkan bantuan ekstra (dan selamat datang!) Dari Hibernate pada anotasi validasi.

Ryan Stewart
sumber
2
Terima kasih! Jadi jika saya ingin kegigihan JPA saya tidak terikat dengan implementasi Hibernate (yaitu, ubah ke EJB3) maka saya harus menggunakan kedua anotasi (untuk melarang nol di bidang dan kolomnya)?
rapt
3
Saya tidak tahu Tidak ada spesifikasi yang mengatakan penyedia JPA harus mengenali penjelasan JSR 303, tetapi itu tidak berarti bahwa penyedia lain tidak. Saya tidak bisa mengatakan apakah ada atau tidak.
Ryan Stewart
7
Penyedia JPA tidak diharuskan untuk menyediakan implementasi JSR303 tetapi sesuai spesifikasi yang diperlukan untuk memberikan kemampuan untuk berintegrasi dengan implementasi JSR303 pihak ketiga mana pun. Jadi, sementara Hibernate menyediakan JSR303, Anda bisa dengan alasan apa pun memutuskan untuk tidak menggunakan JSR303 dan menggunakan orang lain atau menggunakan implementasi JPA seperti openJPA dan menggunakan orang lain untuk memberikan JSR303. Juga perhatikan implementasi JPA Hibernate juga EJB3. Tidak benar untuk mengatakan 'jika saya ingin kegigihan JPA saya tidak terikat dengan implementasi Hibernate (yaitu, ubah ke EJB3)' JPA adalah bagian dari spesifikasi EJB3.
Shahzeb
5
@ Shahzeb: Pertanyaannya bukan tentang siapa yang mendukung / menyediakan validasi JSR 303. Ini tentang yang ORM (s) mengakui JSR 303 penjelasan seperti @NotNull, @Size, @Min, @Max, dll, dan menerjemahkan ke dalam kendala database.
Ryan Stewart
1
Ya tapi komentar saya valid dalam konteks apa yang diminta OP dalam komentar selanjutnya yang tidak Anda ketahui.
Shahzeb
18

Versi terbaru dari penyedia JPA hibernasi menerapkan batasan validasi bean (JSR 303) seperti @NotNulluntuk DDL secara default (terima kasih kepada hibernate.validator.apply_to_ddl propertydefault untuktrue ). Tetapi tidak ada jaminan bahwa penyedia JPA lain melakukan atau bahkan memiliki kemampuan untuk melakukan itu.

Anda harus menggunakan anotasi validasi kacang @NotNulluntuk memastikan, bahwa properti kacang diatur ke nilai tidak-nol, ketika memvalidasi kacang java di JVM (ini tidak ada hubungannya dengan kendala basis data, tetapi dalam kebanyakan situasi harus sesuai dengan mereka).

Anda juga harus menggunakan anotasi JPA seperti @Column(nullable = false)untuk memberikan petunjuk penyedia jpa untuk menghasilkan DDL yang tepat untuk membuat kolom tabel dengan batasan database yang Anda inginkan. Jika Anda bisa atau ingin mengandalkan penyedia JPA seperti Hibernate, yang menerapkan batasan validasi bean ke DDL secara default, maka Anda bisa menghilangkannya.

Sebastian Theek
sumber
10

Menarik untuk dicatat, semua sumber menekankan bahwa @Column (nullable = false) hanya digunakan untuk generasi DDL.

Namun, bahkan jika tidak ada penjelasan @NotNull, dan opsi hibernate.check_nullability disetel ke true, Hibernate akan melakukan validasi entitas yang akan dipertahankan.

Ini akan melempar PropertyValueException mengatakan bahwa "properti tidak-nol merujuk nilai nol atau sementara", jika nullable = atribut palsu tidak memiliki nilai, bahkan jika pembatasan tersebut tidak diterapkan pada lapisan database.

Informasi lebih lanjut tentang opsi hibernate.check_nullability tersedia di sini: http://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#configurations-mapping .

Aleksandar Radulović
sumber
7

JPA @ColumnAnotasi

The nullableatribut dari @Columnpenjelasan memiliki dua tujuan:

  • ini digunakan oleh alat pembuat skema
  • itu digunakan oleh Hibernate selama membilas Konteks Persistence

Alat Pembuatan Skema

Alat pembuatan skema HBM2DDL menerjemahkan @Column(nullable = false)atribut entitas ke NOT NULLkendala untuk kolom tabel terkait saat membuat CREATE TABLEpernyataan.

Seperti yang saya jelaskan dalam Panduan Pengguna Hibernate , lebih baik menggunakan alat seperti Flyway daripada mengandalkan mekanisme HBM2DDL untuk menghasilkan skema database.

Persistensi Konteks Flush

Saat membilas Konteks Kegigihan, Hibernate ORM juga menggunakan @Column(nullable = false)atribut entitas:

new Nullability( session ).checkNullability( values, persister, true );

Jika validasi gagal, Hibernate akan melempar a PropertyValueException, dan mencegah pernyataan INSERT atau UPDATE untuk dieksekusi dengan perlu:

if ( !nullability[i] && value == null ) {
    //check basic level one nullablilty
    throw new PropertyValueException(
            "not-null property references a null or transient value",
            persister.getEntityName(),
            persister.getPropertyNames()[i]
        );    
}

Untuk detail lebih lanjut tentang cara kerja mekanisme siram Hibernate, lihat artikel ini .

@NotNullAnotasi Validasi Bean

The @NotNullpenjelasan didefinisikan oleh Bean Validasi dan, seperti Hibernate ORM yang paling populer implementasi JPA, yang paling populer pelaksanaan Bean Validasi adalah Hibernate Validator kerangka.

Saat menggunakan Hibernate Validator bersama dengan Hibernate ORM, Hibernate Validator akan melempar ConstraintViolationketika memvalidasi entitas.

Vlad Mihalcea
sumber
Mengapa Anda menyatakan bahwa jalur terbang lebih baik daripada menghasilkan skema?
Andronicus
1
Itu pengamatan yang bagus. Saya memperbarui jawabannya dengan tautan referensi.
Vlad Mihalcea
Terima kasih untuk referensi dan jawaban yang bagus!
Andronicus