Entiti JPA && Hubungan DB
Selamat hari, rakan sekerja!Apa itu Entiti?
Entiti ialah objek daripada kehidupan sebenar (contohnya, kereta) yang mempunyai atribut (pintu, RODA , enjin). Entiti DB: Dalam kes ini, entiti kami disimpan dalam DB, semuanya mudah. Mengapa dan bagaimana kami meletakkan kereta itu ke dalam pangkalan data - kami akan melihatnya kemudian.Apakah itu Perhubungan DB?
Pada masa dahulu, di kerajaan yang jauh , DB hubungan telah dicipta . Dalam DB ini, data dibentangkan dalam bentuk jadual. Tetapi keldai dari Shrek juga memahami bahawa perlu mewujudkan mekanisme untuk menyambungkan jadual ini. Akibatnya, 4 perhubungan DB muncul : Jika anda melihat semua ini buat kali pertama, saya memberi amaran kepada anda sekali lagi - ia akan menjadi lebih teruk: fikirkan untuk berjalan-jalan. Kami akan menganalisis semua perhubungan ini menggunakan contoh, dan memahami perbezaan antara mereka.Contoh Seram
Kami akan mempunyai satu projek yang akan mempunyai 5 cawangan: master, di mana akan terdapat penerangan projek dan 1 cawangan untuk setiap perhubungan DB. Setiap cawangan akan mengandungi skrip SQL untuk mencipta DB dan mengisinya dengan data ujian, serta kelas Entiti dengan pemetaan anotasi. Terdapat juga fail konfigurasi Hibernate untuk setiap cawangan. Saya akan menggunakan DB terbenam H2 untuk projek itu supaya tidak terganggu oleh aspek individu DB awan atau DB luaran. Dengan mengikuti pautan, pasang H2 DB pada pembersih vakum anda. Saya akan menerangkan setiap langkah dalam 1 cawangan, selebihnya hanyalah perkara utama. Pada akhirnya kita akan meringkaskan. Pergi. Ini adalah pautan ke cawangan induk projek saya.Hubungan Satu dengan Satu
Pautan ke cawangan di sini .-
Kami perlu menyambungkan H2 DB ke projek kami. Di sini kita perlu menekankan bahawa kita memerlukan Ultimate IDEA untuk bekerja dengan selesa dengan DB dan perkara lain. Jika anda sudah memilikinya, pergi terus ke sambungan DB. Pergi ke tab Pangkalan Data dan lakukan seperti dalam tangkapan skrin:
Seterusnya kita beralih ke tetapan DB. Anda boleh memasukkan data anda, dan juga DBMS anda; Saya ulangi, saya menggunakan H2 DB untuk kesederhanaan.
Seterusnya, mari kita sediakan litar. Langkah ini adalah pilihan tetapi disyorkan jika anda mempunyai berbilang skema dalam DB.
Gunakan tetapan, dan pada akhirnya kita akan mendapat sesuatu seperti ini:
-
Kami mencipta pangkalan data dan mengkonfigurasi akses kepadanya daripada IDEA. Sekarang anda perlu membuat jadual di dalamnya dan mengisinya dengan beberapa data. Sebagai contoh, saya akan mengambil dua entiti: Pengarang dan Buku. Sebuah buku mungkin mempunyai pengarang, mungkin mempunyai beberapa pengarang, atau mungkin tidak mempunyai satu. Dalam contoh ini kita akan membuat semua jenis sambungan. Tetapi pada ketika ini - hubungan Satu-dengan-Satu. Mari buat skrip sepadan yang mencipta Jadual 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 laksanakannya:
Hasil pelaksanaan dalam konsol:
Keputusan dalam DB:
-
Mari lihat gambar rajah jadual kami. Untuk melakukan ini, RMB pada DB kami:
Keputusan:
Pada rajah UML kita boleh melihat semua kunci utama dan kunci asing, kita juga melihat sambungan antara jadual kita.
-
Mari tulis skrip yang mengisi DB kami dengan data ujian:
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);
Maksud saya, apa yang berlaku? Perhubungan satu-dengan-Satu diperlukan apabila entiti satu jadual berkaitan dengan satu entiti yang lain (atau tidak berkaitan langsung jika NOT NULL dialih keluar daripada BOOK_ID). Dalam contoh kita, satu buku WAJIB ada seorang pengarang. Tiada jalan lain.
-
Sekarang perkara yang paling menarik ialah bagaimana untuk menyambungkan kelas Java dengan entiti DB? Sangat ringkas. Mari buat dua kelas Buku dan Pengarang. Menggunakan contoh, saya akan menganalisis kelas 1 dan medan komunikasi utama. Mari kita ambil kelas Pengarang 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 medan dalam kelas mengulangi atribut entiti DB.
- @Data (dari Lombok ) mengatakan bahawa untuk setiap medan pengambil dan penetap akan dibuat, sama, kod cincang akan ditindih dan kaedah toString akan dijana.
- @Entity mengatakan bahawa kelas yang diberikan ialah entiti dan dikaitkan dengan entiti DB.
- @DynamicInsert dan @DynamicUpdate mengatakan bahawa sisipan dinamik dan kemas kini akan dilakukan dalam DB. Ini adalah tetapan Hibernate yang lebih mendalam yang akan berguna kepada anda supaya anda mempunyai kumpulan yang BETUL.
- @Table (nama = "AUTHOR") mengikat kelas Buku ke jadual DB AUTHOR.
- @Id mengatakan bahawa medan ini adalah kunci utama.
- @GeneratedValue (strategi = GenerationType.IDENTITY) – strategi penjanaan kunci utama.
- @Column (name = "ID", nullable = false) mengaitkan medan dengan atribut DB, dan juga mengatakan bahawa medan DB yang diberikan tidak boleh batal. Ini juga berguna apabila menjana jadual daripada entiti. Proses terbalik kepada cara kami mencipta projek kami sekarang, ini diperlukan dalam DB ujian untuk ujian Unit.
- @OneToOne mengatakan bahawa medan yang diberikan ialah medan perhubungan One-to-One.
- @JoinColumn (nama = "BOOK_ID", unique = true, nullable = false) - lajur BOOK_ID akan dibuat, yang unik dan bukan batal.
-
Sekarang mari kita konfigurasikan Hibernate. Untuk melakukan ini, buat fail 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 ialah dialek DBMS yang telah kami pilih.
- hibernate.connection.driver_class - Kelas pemandu DB kami.
- hibernate.connection.url - utl DB kami. Anda boleh mengambilnya dari titik pertama di mana kami mengkonfigurasi DB.
- hibernate.connection.username - nama pengguna DB.
- hibernate.connection.password — kata laluan pengguna DB.
- hibernate.hbm2ddl.auto - menyediakan penjanaan jadual. Jika kemas kini, maka ia tidak menjana jika ia telah dibuat, tetapi hanya mengemas kininya.
- hibernate.show_sql - sama ada untuk menunjukkan pertanyaan DB.
- hibernate.format_sql - sama ada hendak memformat pertanyaan DB. Jika tidak, maka mereka semua akan berada pada satu baris. Saya cadangkan menghidupkannya.
- hibernate.use_sql_comments - mengulas pertanyaan DB. Jika ini adalah Sisipan, maka ulasan ditulis di atas permintaan bahawa permintaan adalah daripada jenis Sisip.
- hibernate.generate_statistics - menjana log. Saya cadangkan dan cadangkan menyediakan pengelogan secara maksimum. Membaca log akan meningkatkan peluang anda untuk bekerja dengan betul dengan ORM.
- hibernate.jdbc.batch_size — Saiz kelompok maksimum.
- hibernate.jdbc.fetch_size — Saiz pengambilan maksimum.
- hibernate.order_inserts - membenarkan sisipan dinamik.
- hibernate.order_updates - Membenarkan kemas kini dinamik.
- hibernate.jdbc.batch_versioned_data - membenarkan batching. Lihat DBMS anda: tidak semua orang menyokong ini.
- kelas pemetaan - kelas yang merupakan entiti kami. Semuanya perlu disenaraikan.
-
Sekarang intipati kita mesti ditentukan. Kita boleh menyemak ini dalam tab kegigihan:
Keputusan:
-
Kami juga perlu mengkonfigurasi data tetapan:
Keputusan: Kami telah melakukan pemetaan One-to-One. Bahan adalah untuk tujuan maklumat sahaja, butiran ada dalam rujukan.
Hubungan Satu-dengan-Banyak
Pautan ke cawangan di sini . Saya tidak lagi akan menyiarkan kod dalam artikel, kerana ia sudah terlalu panjang. Kami melihat semua kod pada GitHub.-
Hasil daripada melaksanakan skrip permulaan, kami mendapat yang berikut:
Adakah anda merasakan perbezaan dengan jadual sebelumnya?
-
rajah:
Hubungan Satu-dengan-Banyak - seorang pengarang boleh mempunyai beberapa buku. Entiti kiri sepadan dengan satu atau lebih entiti kanan.
-
Perbezaan dalam pemetaan adalah dalam anotasi dan medan:
Medan muncul dalam kelas Pengarang :
@OneToMany(fetch = FetchType.LAZY, mappedBy = "author") private Set<Book> books;
Ia sudah satu set, kerana kita boleh mempunyai beberapa buku. @OneToMany bercakap tentang jenis sikap. FetchType.Lazy mengatakan bahawa kami tidak perlu memuatkan keseluruhan senarai buku jika ia tidak dinyatakan dalam permintaan. Ia juga harus dikatakan bahawa medan ini TIDAK BOLEH ditambahkan pada toString, jika tidak, kami akan mula menghisap StackOverflowError. Lombok tercinta saya menjaga ini:
@ToString(exclude = "books")
Dalam kelas Buku kami melakukan maklum balas Ramai-ke-Satu:
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "AUTHOR_ID", nullable = false) private Author author;
Di sini kita membuat kesimpulan bahawa Satu-ke-Ramai ialah imej cermin Ramai-ke-Satu dan sebaliknya. Perlu ditekankan bahawa Hibernate tidak tahu apa-apa tentang komunikasi dua arah. Baginya, ini adalah dua sambungan yang berbeza: satu dalam satu arah, satu lagi dalam arah yang bertentangan.
-
Tiada banyak yang berubah dalam hibernate.cfg.xml .
-
Kegigihan:
Hubungan Ramai-dengan-Satu
Memandangkan Many-to-One ialah imej cermin One-to-Many, akan ada sedikit perbezaan. Pautan ke cawangan di sini .-
Hasil daripada melaksanakan skrip permulaan, kami mendapat hasil berikut:
-
rajah:
-
Perbezaan dalam pemetaan adalah dalam anotasi dan medan:
Tiada lagi set dalam kelas Pengarang , kerana ia telah berpindah ke kelas Buku .
-
Kegigihan:
Hubungan Ramai dengan Ramai
Mari kita beralih kepada hubungan yang paling menarik. Hubungan ini, mengikut semua peraturan kesopanan dan kesusilaan, dicipta melalui jadual tambahan. Tetapi jadual ini bukan entiti. Menarik kan? Mari kita lihat najis ini. Pautan ke cawangan di sini .-
Lihat skrip permulaan , jadual HAS tambahan muncul di sini. Kami mendapat sesuatu seperti penulis-mempunyai-buku.
Hasil daripada melaksanakan skrip, kami akan mendapat jadual berikut:
-
rajah:
Dalam contoh kami, ternyata sebuah buku boleh mempunyai ramai pengarang, dan seorang pengarang boleh mempunyai banyak buku. Mereka mungkin bertindih.
-
Kelas pemetaan akan mempunyai set dalam kelas. Tetapi seperti yang saya katakan, jadual HAS bukan entiti.
Kelas pengarang :
@ManyToMany @JoinTable(name = "HAS", joinColumns = @JoinColumn(name = "AUTHOR_ID", referencedColumnName = "ID"), inverseJoinColumns = @JoinColumn(name = "BOOK_ID", referencedColumnName = "ID") ) private Set<Book> books;
@ManyToMany ialah sejenis perhubungan.
@JoinTable - inilah yang akan menyambungkan atribut dengan jadual HAS tambahan. Di dalamnya kami menentukan dua atribut yang akan menunjuk kepada kunci utama dua entiti.
Kelas buku :
@ManyToMany(fetch = FetchType.LAZY, mappedBy = "books") private Set<Author> authors;
Di sini kami menunjukkan FetchType dan medan yang akan kami gunakan untuk memetakan.
-
hibernate.cfg.xml kami sekali lagi kekal tidak berubah (saya tidak mengambil kira hakikat bahawa kami mencipta DB baharu untuk setiap cawangan).
-
Kegigihan:
Taklimat
Jadi, kami telah mengkaji secara cetek jenis perhubungan DB dan memikirkan cara melaksanakannya dalam model ORM. Kami menulis projek ujian yang menunjukkan semua sambungan, dan mengetahui cara mengkonfigurasi hibernate / jpa. Fuh.pautan yang berguna
- Sebenarnya projek itu sendiri
- Satu-ke-Satu cawangan
- Cawangan Satu-ke-Banyak
- Cawangan Banyak-ke-Satu
- Cawangan Banyak-ke-Banyak
- Membacanya
- Dan bacalah
GO TO FULL VERSION