JavaRush /Java Blog /Random-ID /Entitas JPA dan Hubungan DB
Nikita Koliadin
Level 40
Днепр

Entitas JPA dan Hubungan DB

Dipublikasikan di grup Random-ID

Entitas JPA && Hubungan DB

Selamat siang, rekan-rekan!
Entitas JPA dan Hubungan DB - 1
Materi ini ditujukan bagi yang sudah mempunyai pemahaman tentang pengorganisasian database (selanjutnya disebut DB - "Database"), pengetahuan minimal tentang cara kerja Object-Relational Mapping (selanjutnya disebut ORM ), dan implementasinya, seperti Hibernate / JPA . Jika Anda belum mengetahuinya, saya menyarankan Anda untuk memulai dengan JDBC , dan baru kemudian beralih ke model ORM. Saya memperingatkan Anda, dan saya tidak bertanggung jawab atas jiwa Anda setelah membaca artikel ini tanpa persiapan yang matang! :) Mari kita mulai menangani semuanya secara berurutan. Pertama, kita akan mempelajari sedikit teorinya, sedikit saja. Kedua, kita akan mencari cara melakukan hal ini di Java favorit semua orang. Kami juga akan menulis lembar contekan proyek untuk Anda, yang akan mengkonsolidasikan pemahaman kami tentang topik tersebut dan berfungsi sebagai templat untuk BAGAIMANA pemetaan harus dilakukan . Jadi, ayo kita lakukan!

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 :
  1. Satu lawan satu
  2. Satu-ke-Banyak
  3. Banyak-ke-Satu
  4. Banyak ke banyak
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 .
  1. 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:

    Entitas JPA dan Hubungan DB - 2

    Selanjutnya kita beralih ke pengaturan DB. Anda dapat memasukkan data Anda, dan bahkan DBMS Anda; Saya ulangi, saya menggunakan H2 DB untuk kesederhanaan.

    Entitas JPA dan Hubungan DB - 3

    Selanjutnya, mari kita siapkan sirkuitnya. Langkah ini opsional tetapi disarankan jika Anda memiliki beberapa skema di DB.

    Entitas JPA dan Hubungan DB - 4

    Terapkan pengaturannya, dan pada akhirnya kita akan mendapatkan sesuatu seperti ini:

    Entitas JPA dan Hubungan DB - 5
  2. 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:

    Entitas JPA dan Hubungan DB - 6

    Hasil eksekusi di konsol:

    Entitas JPA dan Hubungan DB - 7

    Hasil dalam DB:

    Entitas JPA dan Hubungan DB - 8
  3. Mari kita lihat diagram tabel kita. Untuk melakukan ini, RMB di DB kami:

    Entitas JPA dan Hubungan DB - 9

    Hasil:

    Entitas JPA dan Hubungan DB - 10

    Pada diagram UML kita dapat melihat semua kunci primer dan kunci asing, kita juga melihat hubungan antar tabel kita.

  4. 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.

  5. 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;
    }
Mari kita lihat secara berurutan:
  1. Semua bidang di kelas mengulangi atribut entitas DB.
  2. @Data (dari Lombok ) mengatakan bahwa untuk setiap bidang, pengambil dan penyetel akan dibuat, sama dengan, kode hash akan diganti, dan metode toString akan dihasilkan.
  3. @Entity mengatakan bahwa kelas yang diberikan adalah suatu entitas dan dikaitkan dengan entitas DB.
  4. @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.
  5. @Table (name = "AUTHOR") mengikat kelas Buku ke tabel DB AUTHOR.
  6. @Id mengatakan bahwa bidang ini adalah kunci utama.
  7. @GeneratedValue (strategy = GenerationType.IDENTITY) – strategi pembuatan kunci utama.
  8. @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.
  9. @OneToOne mengatakan bahwa bidang yang diberikan adalah bidang hubungan Satu-ke-Satu.
  10. @JoinColumn (name = "BOOK_ID", unik = true, nullable = false) - kolom BOOK_ID akan dibuat, yang unik dan bukan null.
Di sisi sebaliknya (di kelas Book ), kita juga perlu membuat koneksi Satu-ke-Satu dan menunjukkan bidang tempat pemetaan terjadi. @OneToOne(mappedBy = "book") - dalam contoh ini, ini adalah bidang buku dari kelas Penulis. JPA akan menghubungkannya sendiri. Pada pandangan pertama, mungkin tampak ada anotasi yang berantakan, namun sebenarnya ini sangat nyaman dan dengan pengalaman Anda akan menambahkannya secara otomatis tanpa berpikir.
  1. 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>
Deskripsi properti :
  1. hibernate.dialect adalah dialek DBMS yang kita pilih.
  2. hibernate.connection.driver_class — Kelas driver DB kami.
  3. hibernate.connection.url - utl DB kami. Anda dapat mengambilnya dari titik pertama di mana kami mengkonfigurasi DB.
  4. hibernate.connection.username - Nama pengguna DB.
  5. hibernate.connection.password — kata sandi pengguna DB.
  6. hibernate.hbm2ddl.auto - menyiapkan pembuatan tabel. Jika diperbarui, maka tidak menghasilkan jika sudah dibuat, tetapi hanya memperbaruinya.
  7. hibernate.show_sql - apakah akan menampilkan kueri DB.
  8. hibernate.format_sql - apakah akan memformat kueri DB. Jika tidak, maka semuanya akan berada pada satu jalur. Saya sarankan untuk menyalakannya.
  9. hibernate.use_sql_comments - mengomentari pertanyaan DB. Jika ini adalah Sisipan, maka komentar ditulis di atas permintaan bahwa permintaan tersebut berjenis Sisipkan.
  10. 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.
  11. hibernate.jdbc.batch_size — Ukuran batch maksimum.
  12. hibernate.jdbc.fetch_size — Ukuran pengambilan maksimum.
  13. hibernate.order_inserts - memungkinkan penyisipan dinamis.
  14. hibernate.order_updates - Memungkinkan pembaruan dinamis.
  15. hibernate.jdbc.batch_versioned_data - memungkinkan pengelompokan. Lihatlah DBMS Anda: tidak semua orang mendukung ini.
  16. kelas pemetaan - kelas yang merupakan entitas kita. Semuanya perlu dicantumkan.
  1. Sekarang esensi kita harus ditentukan. Kita dapat memeriksanya di tab persistensi:

    Entitas JPA dan Hubungan DB - 11

    Hasil:

    Entitas JPA dan Hubungan DB - 12
  2. Kita juga perlu mengonfigurasi data penetapan:

    Entitas JPA dan Hubungan DB - 13 Entitas JPA dan Hubungan DB - 14

    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.
  1. Sebagai hasil dari menjalankan skrip inisialisasi, kami mendapatkan yang berikut:

    Entitas JPA dan Hubungan DB - 15

    Apakah Anda merasakan perbedaannya dengan tabel sebelumnya?

  2. Diagram:

    Entitas JPA dan Hubungan DB - 16

    Hubungan Satu-ke-Banyak - satu penulis dapat memiliki beberapa buku. Entitas kiri berhubungan dengan satu atau lebih entitas kanan.

  3. 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.

  4. Tidak banyak yang berubah di hibernate.cfg.xml .

  5. Kegigihan:

    Entitas JPA dan Hubungan DB - 17

Hubungan Banyak-ke-Satu

Karena Banyak-ke-Satu adalah cerminan dari Satu-ke-Banyak, hanya ada sedikit perbedaan. Tautan ke cabang di sini .
  1. Sebagai hasil dari menjalankan skrip inisialisasi, kami mendapatkan hasil berikut:

    Entitas JPA dan Hubungan DB - 18
  2. Diagram:

    Entitas JPA dan Hubungan DB - 19
  3. Perbedaan dalam pemetaan terletak pada anotasi dan kolom:

    Tidak ada lagi satu set di kelas Penulis , karena telah dipindahkan ke kelas Buku .

  4. hibernasi.cfg.xml

  5. Kegigihan:

    Entitas JPA dan Hubungan DB - 20

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 .
  1. 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:

    Entitas JPA dan Hubungan DB - 21
  2. Diagram:

    Entitas JPA dan Hubungan DB - 22

    Dalam contoh kita, ternyata sebuah buku bisa mempunyai banyak penulis, dan seorang penulis bisa memiliki banyak buku. Mereka mungkin tumpang tindih.

  3. 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.

  4. Hibernate.cfg.xml kami sekali lagi tetap tidak berubah (saya tidak memperhitungkan fakta bahwa kami membuat DB baru untuk setiap cabang).

  5. Kegigihan:

    Entitas JPA dan Hubungan DB - 23

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

Artikel saya sebelumnya: PS Mungkin ada kesalahan dan kekurangan dalam teks. PPS Penulis merasakan sesuatu yang aneh saat menulis artikel ini. Terima kasih atas perhatian Anda!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION