Entitas JPA && Hubungan DB
Selamat siang, rekan-rekan!Apa itu Entitas?
Entitas adalah objek dari kehidupan nyata (misalnya mobil) yang memiliki atribut (pintu, RODA , mesin). Entitas DB: Dalam hal ini, entitas kita disimpan dalam DB, semuanya sederhana. Mengapa dan bagaimana kami memasukkan mobil ke dalam database - kami akan melihatnya nanti.Apa itu Hubungan DB?
Dahulu kala, di kerajaan yang jauh , DB relasional telah dibuat . Pada DB ini data disajikan dalam bentuk tabel. Namun jelas juga bagi keledai dari Shrek bahwa perlu dibuat mekanisme untuk menghubungkan tabel-tabel ini. Hasilnya, 4 hubungan DB muncul : Jika Anda melihat semua ini untuk pertama kalinya, saya peringatkan Anda lagi - ini akan menjadi lebih buruk: pikirkan untuk berjalan-jalan. Kami akan menganalisis semua hubungan ini dengan menggunakan sebuah contoh, dan memahami perbedaan di antara keduanya.Contoh Horor
Kami akan memiliki satu proyek yang memiliki 5 cabang: master, di mana akan ada deskripsi proyek, dan 1 cabang untuk setiap hubungan DB. Setiap cabang akan berisi skrip SQL untuk membuat DB dan mengisinya dengan data pengujian, ditambah kelas Entitas dengan pemetaan anotasi. Juga akan ada file konfigurasi Hibernate untuk setiap cabang. Saya akan menggunakan DB yang tertanam H2 untuk proyek ini agar tidak terganggu oleh aspek individual dari DB cloud atau DB eksternal. Dengan mengikuti tautan, instal H2 DB pada penyedot debu Anda. Saya akan menjelaskan setiap langkah dalam 1 cabang, selebihnya hanyalah poin-poin penting. Pada akhirnya kami akan meringkasnya. Pergi. Ini adalah tautan ke cabang master proyek saya.Hubungan Satu-ke-Satu
Tautan ke cabang di sini .-
Kita perlu menghubungkan H2 DB ke proyek kita. Di sini kami perlu menekankan bahwa kami memerlukan Ultimate IDEA untuk bekerja dengan nyaman dengan DB dan hal lainnya. Jika sudah memilikinya maka langsung masuk ke koneksi DB. Buka tab Database dan lakukan seperti pada tangkapan layar:
Selanjutnya kita beralih ke pengaturan DB. Anda dapat memasukkan data Anda, dan bahkan DBMS Anda; Saya ulangi, saya menggunakan H2 DB untuk kesederhanaan.
Selanjutnya, mari kita siapkan sirkuitnya. Langkah ini opsional tetapi disarankan jika Anda memiliki beberapa skema di DB.
Terapkan pengaturannya, dan pada akhirnya kita akan mendapatkan sesuatu seperti ini:
-
Kami membuat database dan mengonfigurasi akses ke sana dari IDEA. Sekarang Anda perlu membuat tabel di dalamnya dan mengisinya dengan beberapa data. Misalnya, saya akan mengambil dua entitas: Penulis dan Buku. Sebuah buku mungkin memiliki seorang penulis, mungkin memiliki banyak penulis, atau mungkin tidak memiliki satu penulis. Dalam contoh ini kita akan membuat semua jenis koneksi. Namun pada titik ini - Hubungan satu lawan satu. Mari buat skrip terkait yang membuat Tabel DB :
DROP TABLE IF EXISTS PUBLIC.BOOK; CREATE TABLE PUBLIC.BOOK ( ID INTEGER NOT NULL AUTO_INCREMENT, NAME VARCHAR(255) NOT NULL, PRINT_YEAR INTEGER(4) NOT NULL, CONSTRAINT BOOK_PRIMARY_KEY PRIMARY KEY (ID) ); DROP TABLE IF EXISTS PUBLIC.AUTHOR; CREATE TABLE PUBLIC.AUTHOR ( ID INTEGER NOT NULL AUTO_INCREMENT, FIRST_NAME VARCHAR(255) NOT NULL, SECOND_NAME VARCHAR(255) NOT NULL, BOOK_ID INTEGER NOT NULL UNIQUE, CONSTRAINT AUTHOR_PRIMARY_KEY PRIMARY KEY (ID), CONSTRAINT BOOK_FOREIGN_KEY FOREIGN KEY (BOOK_ID) REFERENCES BOOK (ID) );
Dan mari kita jalankan:
Hasil eksekusi di konsol:
Hasil dalam DB:
-
Mari kita lihat diagram tabel kita. Untuk melakukan ini, RMB di DB kami:
Hasil:
Pada diagram UML kita dapat melihat semua kunci primer dan kunci asing, kita juga melihat hubungan antar tabel kita.
-
Mari kita menulis skrip yang mengisi DB kita dengan data pengujian:
INSERT INTO PUBLIC.BOOK (NAME, PRINT_YEAR) VALUES ('First book', 2010), ('Second book', 2011), ('Third book', 2012); INSERT INTO PUBLIC.AUTHOR (FIRST_NAME, SECOND_NAME, BOOK_ID) VALUES ('Pablo', 'Lambado', 1), ('Pazo', 'Zopa', 2), ('Lika', 'Vika', 3);
Maksudku, apa yang terjadi? Hubungan satu-ke-Satu diperlukan ketika entitas suatu tabel terkait dengan satu entitas tabel lainnya (atau tidak terkait sama sekali jika NOT NULL dihapus dari BOOK_ID). Dalam contoh kita, satu buku HARUS memiliki satu penulis. Tidak ada jalan lain.
-
Sekarang yang paling menarik adalah bagaimana menghubungkan kelas Java dengan entitas DB? Sangat sederhana. Mari kita buat dua kelas Buku dan Penulis. Dengan menggunakan contoh, saya akan menganalisis kelas 1 dan bidang komunikasi utama. Mari kita ambil kelas Author sebagai contoh :
@Data @Entity @DynamicInsert @DynamicUpdate @Table(name = "AUTHOR") public class Author { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ID", nullable = false) private Long id; @Column(name = "FIRST_NAME", nullable = false) private String firstName; @Column(name = "SECOND_NAME", nullable = false) private String secondName; @OneToOne @JoinColumn(name = "BOOK_ID", unique = true, nullable = false) private Book book; }
- Semua bidang di kelas mengulangi atribut entitas DB.
- @Data (dari Lombok ) mengatakan bahwa untuk setiap bidang, pengambil dan penyetel akan dibuat, sama dengan, kode hash akan diganti, dan metode toString akan dihasilkan.
- @Entity mengatakan bahwa kelas yang diberikan adalah suatu entitas dan dikaitkan dengan entitas DB.
- @DynamicInsert dan @DynamicUpdate mengatakan bahwa penyisipan dan pembaruan dinamis akan dilakukan di DB. Ini adalah pengaturan Hibernasi yang lebih dalam yang akan berguna bagi Anda sehingga Anda mendapatkan pengelompokan yang BENAR.
- @Table (name = "AUTHOR") mengikat kelas Buku ke tabel DB AUTHOR.
- @Id mengatakan bahwa bidang ini adalah kunci utama.
- @GeneratedValue (strategy = GenerationType.IDENTITY) – strategi pembuatan kunci utama.
- @Column (name = "ID", nullable = false) mengaitkan bidang dengan atribut DB, dan juga mengatakan bahwa bidang DB yang diberikan tidak boleh nol. Ini juga berguna saat membuat tabel dari entitas. Proses kebalikan dari cara kita membuat proyek sekarang, ini diperlukan dalam pengujian DB untuk pengujian Unit.
- @OneToOne mengatakan bahwa bidang yang diberikan adalah bidang hubungan Satu-ke-Satu.
- @JoinColumn (name = "BOOK_ID", unik = true, nullable = false) - kolom BOOK_ID akan dibuat, yang unik dan bukan null.
-
Sekarang mari kita konfigurasikan Hibernate. Untuk melakukannya, buat file hibernate.cfg.xml :
<?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property> <property name="hibernate.connection.driver_class">org.h2.Driver</property> <property name="hibernate.connection.url">jdbc:h2:~/db/onetoone</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"/> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.use_sql_comments">true</property> <property name="hibernate.generate_statistics">true</property> <property name="hibernate.jdbc.batch_size">50</property> <property name="hibernate.jdbc.fetch_size">50</property> <property name="hibernate.order_inserts">true</property> <property name="hibernate.order_updates">true</property> <property name="hibernate.jdbc.batch_versioned_data">true</property> <mapping class="com.qthegamep.forjavarushpublication2.entity.Book"/> <mapping class="com.qthegamep.forjavarushpublication2.entity.Author"/> </session-factory> </hibernate-configuration>
- hibernate.dialect adalah dialek DBMS yang kita pilih.
- hibernate.connection.driver_class — Kelas driver DB kami.
- hibernate.connection.url - utl DB kami. Anda dapat mengambilnya dari titik pertama di mana kami mengkonfigurasi DB.
- hibernate.connection.username - Nama pengguna DB.
- hibernate.connection.password — kata sandi pengguna DB.
- hibernate.hbm2ddl.auto - menyiapkan pembuatan tabel. Jika diperbarui, maka tidak menghasilkan jika sudah dibuat, tetapi hanya memperbaruinya.
- hibernate.show_sql - apakah akan menampilkan kueri DB.
- hibernate.format_sql - apakah akan memformat kueri DB. Jika tidak, maka semuanya akan berada pada satu jalur. Saya sarankan untuk menyalakannya.
- hibernate.use_sql_comments - mengomentari pertanyaan DB. Jika ini adalah Sisipan, maka komentar ditulis di atas permintaan bahwa permintaan tersebut berjenis Sisipkan.
- hibernate.generate_statistics - menghasilkan log. Saya rekomendasikan dan rekomendasikan untuk mengatur logging secara maksimal. Membaca log akan meningkatkan peluang Anda untuk bekerja dengan benar dengan ORM.
- hibernate.jdbc.batch_size — Ukuran batch maksimum.
- hibernate.jdbc.fetch_size — Ukuran pengambilan maksimum.
- hibernate.order_inserts - memungkinkan penyisipan dinamis.
- hibernate.order_updates - Memungkinkan pembaruan dinamis.
- hibernate.jdbc.batch_versioned_data - memungkinkan pengelompokan. Lihatlah DBMS Anda: tidak semua orang mendukung ini.
- kelas pemetaan - kelas yang merupakan entitas kita. Semuanya perlu dicantumkan.
-
Sekarang esensi kita harus ditentukan. Kita dapat memeriksanya di tab persistensi:
Hasil:
-
Kita juga perlu mengonfigurasi data penetapan:
Hasil: Kami telah melakukan pemetaan One-to-One. Materi hanya untuk tujuan informasi, detailnya ada di referensi.
Hubungan Satu-ke-Banyak
Tautan ke cabang di sini . Saya tidak akan memposting kode lagi di artikel, karena sudah terlalu panjang. Kami melihat semua kode di GitHub.-
Sebagai hasil dari menjalankan skrip inisialisasi, kami mendapatkan yang berikut:
Apakah Anda merasakan perbedaannya dengan tabel sebelumnya?
-
Diagram:
Hubungan Satu-ke-Banyak - satu penulis dapat memiliki beberapa buku. Entitas kiri berhubungan dengan satu atau lebih entitas kanan.
-
Perbedaan dalam pemetaan terletak pada anotasi dan kolom:
Sebuah bidang muncul di kelas Penulis :
@OneToMany(fetch = FetchType.LAZY, mappedBy = "author") private Set<Book> books;
Sudah satu set, karena kita bisa punya beberapa buku. @OneToMany berbicara tentang tipe sikap. FetchType.Lazy mengatakan bahwa kita tidak perlu memuat seluruh daftar buku jika tidak ditentukan dalam permintaan. Perlu juga dikatakan bahwa bidang ini TIDAK BISA ditambahkan ke toString, jika tidak, kita akan mulai menerapkan StackOverflowError. Lombok tercinta mengurus hal ini:
@ToString(exclude = "books")
Di kelas Buku kami melakukan umpan balik Banyak-ke-Satu:
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "AUTHOR_ID", nullable = false) private Author author;
Di sini kita menyimpulkan bahwa Satu-ke-Banyak adalah cerminan dari Banyak-ke-Satu dan sebaliknya. Perlu ditekankan bahwa Hibernate tidak mengetahui apa pun tentang komunikasi dua arah. Baginya, ini adalah dua hubungan yang berbeda: satu dalam satu arah, yang lainnya berlawanan arah.
-
Tidak banyak yang berubah di hibernate.cfg.xml .
-
Kegigihan:
Hubungan Banyak-ke-Satu
Karena Banyak-ke-Satu adalah cerminan dari Satu-ke-Banyak, hanya ada sedikit perbedaan. Tautan ke cabang di sini .-
Sebagai hasil dari menjalankan skrip inisialisasi, kami mendapatkan hasil berikut:
-
Diagram:
-
Perbedaan dalam pemetaan terletak pada anotasi dan kolom:
Tidak ada lagi satu set di kelas Penulis , karena telah dipindahkan ke kelas Buku .
-
Kegigihan:
Hubungan Banyak ke Banyak
Mari beralih ke hubungan yang paling menarik. Hubungan ini, menurut semua aturan kesopanan dan ketidaksenonohan, dibuat melalui tabel tambahan. Namun tabel ini bukanlah sebuah entitas. Menarik bukan? Mari kita lihat omong kosong ini. Tautan ke cabang di sini .-
Lihatlah skrip inisialisasi , tabel HAS tambahan muncul di sini. Kami mendapatkan sesuatu seperti penulis-memiliki-buku.
Sebagai hasil dari mengeksekusi skrip, kita akan mendapatkan tabel berikut:
-
Diagram:
Dalam contoh kita, ternyata sebuah buku bisa mempunyai banyak penulis, dan seorang penulis bisa memiliki banyak buku. Mereka mungkin tumpang tindih.
-
Kelas pemetaan akan memiliki set di dalam kelas. Namun seperti yang saya katakan, tabel HAS bukanlah suatu entitas.
Kelas penulis :
@ManyToMany @JoinTable(name = "HAS", joinColumns = @JoinColumn(name = "AUTHOR_ID", referencedColumnName = "ID"), inverseJoinColumns = @JoinColumn(name = "BOOK_ID", referencedColumnName = "ID") ) private Set<Book> books;
@ManyToMany adalah jenis hubungan.
@JoinTable - inilah yang akan menghubungkan atribut dengan tabel HAS tambahan. Di dalamnya kita menentukan dua atribut yang akan menunjuk ke kunci utama dari dua entitas.
Kelas buku :
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "books") private Set<Author> authors;
Di sini kami menunjukkan FetchType dan bidang yang akan kami gunakan untuk memetakan.
-
Hibernate.cfg.xml kami sekali lagi tetap tidak berubah (saya tidak memperhitungkan fakta bahwa kami membuat DB baru untuk setiap cabang).
-
Kegigihan:
Tanya jawab
Jadi, kami telah memeriksa secara dangkal jenis hubungan DB dan menemukan cara mengimplementasikannya dalam model ORM. Kami menulis proyek pengujian yang mendemonstrasikan semua koneksi, dan menemukan cara mengkonfigurasi hibernasi/jpa. Fiuh.tautan yang bermanfaat
- Sebenarnya proyek itu sendiri
- Cabang satu-ke-satu
- Cabang Satu-ke-Banyak
- Cabang Banyak-ke-Satu
- Cabang Banyak-ke-Banyak
- Membacanya
- Dan membacanya
GO TO FULL VERSION