JavaRush /Blog Java /Random-MS /Entiti JPA dan Hubungan DB
Nikita Koliadin
Tahap
Днепр

Entiti JPA dan Hubungan DB

Diterbitkan dalam kumpulan

Entiti JPA && Hubungan DB

Selamat hari, rakan sekerja!
Entiti JPA dan Hubungan DB - 1
Bahan ini bertujuan untuk mereka yang sudah mempunyai pemahaman tentang organisasi pangkalan data (selepas ini hanya DB - "Pangkalan Data"), pengetahuan minimum tentang cara Pemetaan Perhubungan Objek berfungsi (selepas ini hanya ORM ), dan pelaksanaannya, seperti Hibernate / JPA . Jika anda tidak biasa dengan ini, saya menasihati anda untuk bermula dengan JDBC , dan kemudian beralih kepada model ORM. Saya memberi amaran kepada anda, dan saya tidak bertanggungjawab untuk jiwa anda selepas membaca artikel ini tanpa persediaan yang betul! :) Mari kita mula menangani segala-galanya dengan teratur. Pertama, kita akan mendalami sedikit teori, sedikit sahaja. Kedua, kami akan memikirkan cara melakukan omong kosong ini dalam Java kegemaran semua orang. Kami juga akan menulis bersama anda helaian penipuan projek, yang akan mengukuhkan pemahaman kami tentang topik dan berfungsi sebagai templat untuk BAGAIMANA pemetaan harus dilakukan . Jadi, Jom buat!

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

    JPA Entities and DB Relationships - 2

    Seterusnya kita beralih ke tetapan DB. Anda boleh memasukkan data anda, dan juga DBMS anda; Saya ulangi, saya menggunakan H2 DB untuk kesederhanaan.

    JPA Entities and DB Relationships - 3

    Seterusnya, mari kita sediakan litar. Langkah ini adalah pilihan tetapi disyorkan jika anda mempunyai berbilang skema dalam DB.

    JPA Entities and DB Relationships - 4

    Gunakan tetapan, dan pada akhirnya kita akan mendapat sesuatu seperti ini:

    JPA Entities and DB Relationships - 5
  2. 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:

    JPA Entities and DB Relationships - 6

    Hasil pelaksanaan dalam konsol:

    JPA Entities and DB Relationships - 7

    Keputusan dalam DB:

    JPA Entities and DB Relationships - 8
  3. Mari lihat gambar rajah jadual kami. Untuk melakukan ini, RMB pada DB kami:

    JPA Entities and DB Relationships - 9

    Keputusan:

    JPA Entities and DB Relationships - 10

    Pada rajah UML kita boleh melihat semua kunci utama dan kunci asing, kita juga melihat sambungan antara jadual kita.

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

  5. 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;
    }
Mari kita fikirkan mengikut urutan:
  1. Semua medan dalam kelas mengulangi atribut entiti DB.
  2. @Data (dari Lombok ) mengatakan bahawa untuk setiap medan pengambil dan penetap akan dibuat, sama, kod cincang akan ditindih dan kaedah toString akan dijana.
  3. @Entity mengatakan bahawa kelas yang diberikan ialah entiti dan dikaitkan dengan entiti DB.
  4. @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.
  5. @Table (nama = "AUTHOR") mengikat kelas Buku ke jadual DB AUTHOR.
  6. @Id mengatakan bahawa medan ini adalah kunci utama.
  7. @GeneratedValue (strategi = GenerationType.IDENTITY) – strategi penjanaan kunci utama.
  8. @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.
  9. @OneToOne mengatakan bahawa medan yang diberikan ialah medan perhubungan One-to-One.
  10. @JoinColumn (nama = "BOOK_ID", unique = true, nullable = false) - lajur BOOK_ID akan dibuat, yang unik dan bukan batal.
Di bahagian belakang (dalam kelas Buku ) kita juga perlu membuat sambungan Satu-ke-Satu dan menunjukkan medan di mana pemetaan berlaku. @OneToOne(mappedBy = "book") - dalam contoh ini, ini ialah medan buku kelas Pengarang. JPA akan menghubungkan mereka sendiri. Pada pandangan pertama, nampaknya terdapat kekacauan anotasi, tetapi sebenarnya ia sangat mudah dan dengan pengalaman anda akan menambahkannya secara automatik tanpa berfikir.
  1. 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>
Perihalan hartanah :
  1. hibernate.dialect ialah dialek DBMS yang telah kami pilih.
  2. hibernate.connection.driver_class - Kelas pemandu DB kami.
  3. hibernate.connection.url - utl DB kami. Anda boleh mengambilnya dari titik pertama di mana kami mengkonfigurasi DB.
  4. hibernate.connection.username - nama pengguna DB.
  5. hibernate.connection.password — kata laluan pengguna DB.
  6. hibernate.hbm2ddl.auto - menyediakan penjanaan jadual. Jika kemas kini, maka ia tidak menjana jika ia telah dibuat, tetapi hanya mengemas kininya.
  7. hibernate.show_sql - sama ada untuk menunjukkan pertanyaan DB.
  8. hibernate.format_sql - sama ada hendak memformat pertanyaan DB. Jika tidak, maka mereka semua akan berada pada satu baris. Saya cadangkan menghidupkannya.
  9. hibernate.use_sql_comments - mengulas pertanyaan DB. Jika ini adalah Sisipan, maka ulasan ditulis di atas permintaan bahawa permintaan adalah daripada jenis Sisip.
  10. 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.
  11. hibernate.jdbc.batch_size — Saiz kelompok maksimum.
  12. hibernate.jdbc.fetch_size — Saiz pengambilan maksimum.
  13. hibernate.order_inserts - membenarkan sisipan dinamik.
  14. hibernate.order_updates - Membenarkan kemas kini dinamik.
  15. hibernate.jdbc.batch_versioned_data - membenarkan batching. Lihat DBMS anda: tidak semua orang menyokong ini.
  16. kelas pemetaan - kelas yang merupakan entiti kami. Semuanya perlu disenaraikan.
  1. Sekarang intipati kita mesti ditentukan. Kita boleh menyemak ini dalam tab kegigihan:

    JPA Entities and DB Relationships - 11

    Keputusan:

    JPA Entities and DB Relationships - 12
  2. Kami juga perlu mengkonfigurasi data tetapan:

    JPA Entities and DB Relationships - 13 JPA Entities and DB Relationships - 14

    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.
  1. Hasil daripada melaksanakan skrip permulaan, kami mendapat yang berikut:

    JPA Entities and DB Relationships - 15

    Adakah anda merasakan perbezaan dengan jadual sebelumnya?

  2. rajah:

    JPA Entities and DB Relationships - 16

    Hubungan Satu-dengan-Banyak - seorang pengarang boleh mempunyai beberapa buku. Entiti kiri sepadan dengan satu atau lebih entiti kanan.

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

  4. Tiada banyak yang berubah dalam hibernate.cfg.xml .

  5. Kegigihan:

    JPA Entities and DB Relationships - 17

Hubungan Ramai-dengan-Satu

Memandangkan Many-to-One ialah imej cermin One-to-Many, akan ada sedikit perbezaan. Pautan ke cawangan di sini .
  1. Hasil daripada melaksanakan skrip permulaan, kami mendapat hasil berikut:

    JPA Entities and DB Relationships - 18
  2. rajah:

    JPA Entities and DB Relationships - 19
  3. Perbezaan dalam pemetaan adalah dalam anotasi dan medan:

    Tiada lagi set dalam kelas Pengarang , kerana ia telah berpindah ke kelas Buku .

  4. hibernate.cfg.xml

  5. Kegigihan:

    JPA Entities and DB Relationships - 20

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

    JPA Entities and DB Relationships - 21
  2. rajah:

    JPA Entities and DB Relationships - 22

    Dalam contoh kami, ternyata sebuah buku boleh mempunyai ramai pengarang, dan seorang pengarang boleh mempunyai banyak buku. Mereka mungkin bertindih.

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

  4. hibernate.cfg.xml kami sekali lagi kekal tidak berubah (saya tidak mengambil kira hakikat bahawa kami mencipta DB baharu untuk setiap cawangan).

  5. Kegigihan:

    JPA Entities and DB Relationships - 23

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

Artikel saya sebelum ini: PS Mungkin terdapat kesilapan dan kekurangan dalam teks. PPS Penulis menghisap sesuatu yang pelik semasa menulis artikel ini. Terima kasih kerana memberi perhatian!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION