JavaRush /Java Blogu /Random-AZ /JPA Müəssisələri və DB Əlaqələri
Nikita Koliadin
Səviyyə
Днепр

JPA Müəssisələri və DB Əlaqələri

Qrupda dərc edilmişdir

JPA Müəssisələri && DB Əlaqələri

Gününüz xeyir, həmkarlar!
JPA Müəssisələri və DB Əlaqələri - 1
Bu material verilənlər bazalarının təşkili (bundan sonra sadəcə olaraq DB - "Verilənlər bazası"), Obyekt-Relational Xəritəçəkmənin necə işlədiyi (bundan sonra sadəcə ORM ) və onun Hibernate kimi həyata keçirilməsi haqqında minimal biliklərə malik olanlar üçün nəzərdə tutulmuşdur. / JPA . Əgər bununla tanış deyilsinizsə, sizə JDBC ilə başlamağı və yalnız sonra ORM modelinə keçməyi məsləhət görürəm. Sizə xəbərdarlıq etdim və bu yazını lazımi hazırlıqsız oxuyandan sonra sizin psixikanıza görə məsuliyyət daşımıram! :) Gəlin hər şeyi qaydasında həll etməyə başlayaq. Əvvəlcə nəzəriyyəni bir az araşdıracağıq, sadəcə bir az. İkincisi, hər kəsin sevimli Java-da bu işi necə edəcəyimizi anlayacağıq. Biz həmçinin sizinlə mövzu haqqında anlayışımızı möhkəmləndirəcək və NECƏ Xəritəçəkmənin aparılması üçün şablon rolunu oynayacaq layihə fırıldaqçı vərəqini yazacağıq . Beləliklə, gəlin bunu edək!

Entity nədir?

Müəssisə atributları (qapılar, TƏKƏRLƏR , mühərrik ) olan real həyatdan bir obyektdir (məsələn, avtomobil ) . DB Müəssisəsi: Bu halda bizim qurumumuz DB-də saxlanılır, hər şey sadədir. Maşını niyə və necə verilənlər bazasına qoyduq - daha sonra baxacağıq.

DB Əlaqələri nədir?

Uzun müddət əvvəl, uzaq səltənətdə , əlaqəli DB yaradılmışdır . Bu DB-də məlumatlar cədvəllər şəklində təqdim edilmişdir. Amma Şrekdən gələn eşşəyə də aydın idi ki, bu masaları bir-birinə bağlamaq üçün mexanizm yaratmaq lazımdır. Nəticədə 4 DB əlaqəsi meydana çıxdı :
  1. Birə-bir
  2. Birdən çoxa
  3. Çox-bir
  4. Çoxdan çoxa
Bütün bunları ilk dəfə görürsünüzsə, sizə bir daha xəbərdarlıq edirəm - daha da pisləşəcək: gəzintiyə çıxmağı düşünün. Bütün bu əlaqələri bir nümunə ilə təhlil edəcəyik və aralarındakı fərqi anlayacağıq.

Dəhşət nümunəsi

5 filialı olacaq bir layihəmiz olacaq: layihənin təsviri olacaq master və hər bir DB əlaqəsi üçün 1 filial. Hər bir filial verilənlər bazası yaratmaq və onu test məlumatları ilə doldurmaq üçün SQL skriptlərini, üstəlik, annotasiya xəritəsi ilə Müəssisə sinfini ehtiva edəcəkdir. Həmçinin, hər bir filial üçün Hibernate konfiqurasiya faylı olacaq. Bulud DB və ya xarici DB-nin fərdi aspektlərindən yayınmamaq üçün layihə üçün H2 daxil edilmiş DB-dən istifadə edəcəyəm . Linkə daxil olaraq, tozsoranınıza H2 DB quraşdırın. Hər addımı 1 budaqda təsvir edəcəyəm, qalanları sadəcə əsas məqamlardır. Sonda ümumiləşdirəcəyik. Get. Bu mənim layihəmin master filialına keçiddir.

Bir-bir Münasibət

Filialın linki burada .
  1. H2 DB-ni layihəmizə qoşmalıyıq. Burada vurğulamalıyıq ki, DB və digər şeylərlə rahat işləmək üçün Ultimate IDEA lazımdır. Əgər sizdə artıq varsa, onda birbaşa DB bağlantısına keçin. Verilənlər bazası sekmesine keçin və ekran görüntüsündə olduğu kimi edin:

    JPA Entities and DB Relationships - 2

    Sonra DB parametrlərinə keçirik. Siz məlumatlarınızı və hətta DBMS-nizi daxil edə bilərsiniz; təkrar edirəm, sadəlik üçün H2 DB-dən istifadə edirəm.

    JPA Entities and DB Relationships - 3

    Sonra, dövrəni quraq. Bu addım isteğe bağlıdır, lakin DB-də bir neçə sxeminiz varsa tövsiyə olunur.

    JPA Entities and DB Relationships - 4

    Parametrləri tətbiq edin və sonda belə bir şey almalıyıq:

    JPA Entities and DB Relationships - 5
  2. Biz verilənlər bazasını yaratdıq və IDEA-dan ona girişi konfiqurasiya etdik. İndi orada cədvəllər yaratmalı və bəzi məlumatlar ilə doldurmalısınız. Məsələn, mən iki varlıq götürəcəyəm: Müəllif və Kitab. Kitabın müəllifi ola bilər, bir neçə müəllifi ola bilər və ya olmaya da bilər. Bu nümunədə biz bütün növ əlaqələr yaradacağıq. Ancaq bu nöqtədə - Bir-bir əlaqə. DB Cədvəllərini yaradan müvafiq skripti yaradaq :

    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)
    );

    Və onu icra edək:

    JPA Entities and DB Relationships - 6

    Konsolda icra nəticəsi:

    JPA Entities and DB Relationships - 7

    DB-də nəticə:

    JPA Entities and DB Relationships - 8
  3. Cədvəllərimizin diaqramına baxaq. Bunu etmək üçün, DB-də RMB:

    JPA Entities and DB Relationships - 9

    Nəticə:

    JPA Entities and DB Relationships - 10

    UML diaqramında biz bütün əsas açarları və xarici açarları görə bilərik, həmçinin cədvəllərimiz arasındakı əlaqəni görürük.

  4. DB-ni test məlumatları ilə dolduran bir skript yazaq :

    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);

    Demək istəyirəm ki, nə baş verir? Bir cədvəlin obyekti digərinin bir obyekti ilə əlaqəli olduqda (və ya BOOK_ID-dən NOT NULL silinərsə, heç bir əlaqəsi olmadıqda) bir-bir əlaqə lazımdır. Bizim nümunəmizdə bir kitabın bir müəllifi olmalıdır. Başqa yol yoxdur.

  5. İndi ən maraqlısı Java sinifini DB obyektləri ilə necə bağlamaq olar? Çox sadə. Kitab və Müəllif iki sinif yaradaq. Bir nümunədən istifadə edərək, 1-ci sinfi və əsas ünsiyyət sahələrini təhlil edəcəyəm. Nümunə olaraq Müəllif sinfini götürək :

    @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;
    }
Gəlin bunu ardıcıllıqla anlayaq:
  1. Sinifdəki bütün sahələr DB obyektinin atributlarını təkrarlayır.
  2. @Data ( Lombok -dan ) deyir ki, hər bir sahə üçün alıcı və təyinedici yaradılacaq, bərabərdir, hashcode ləğv ediləcək və toString metodu yaradılacaq.
  3. @Entity deyir ki, verilmiş sinif bir varlıqdır və DB obyekti ilə əlaqələndirilir.
  4. @DynamicInsert@DynamicUpdate dinamik əlavələrin və yeniləmələrin DB-də yerinə yetiriləcəyini bildirir. Bunlar sizin üçün faydalı olacaq daha dərin Hibernate parametrləridir ki, siz DÜZGÜN yığım əldə edəsiniz.
  5. @Cədvəl (ad = "AUTHOR") Kitab sinfini DB AUTHOR cədvəlinə bağlayır.
  6. @Id deyir ki, bu sahə əsas açardır.
  7. @GeneratedValue (strategiya = GenerationType.IDENTITY) – əsas açar yaratma strategiyası.
  8. @Column (ad = "ID", null = false) sahəni DB atributu ilə əlaqələndirir və həmçinin verilmiş DB sahəsinin null ola bilməyəcəyini bildirir. Bu, obyektlərdən cədvəllər yaradan zaman da faydalıdır. İndi layihəmizi necə yaratdığımıza əks proses, vahid testləri üçün test DB-lərində lazımdır.
  9. @OneToOne deyir ki, verilmiş sahə Bir-bir əlaqə sahəsidir.
  10. @JoinColumn (ad = "BOOK_ID", unikal = doğru, null edilə bilən = false) - unikal və null olmayan BOOK_ID sütunu yaradılacaq.
Arxa tərəfdə ( Kitab sinfində ) biz də Bir-bir əlaqə yaratmalı və xəritələşdirmənin baş verdiyi sahəni göstərməliyik. @OneToOne(mappedBy = "kitab") - bu nümunədə bu, Müəllif sinfinin kitab sahəsidir. JPA onları özü birləşdirəcək. İlk baxışdan annotasiyaların qarışıq olduğu görünə bilər, amma əslində bu, çox rahatdır və təcrübə ilə onları heç düşünmədən avtomatik əlavə edəcəksiniz.
  1. İndi Hibernate rejimini konfiqurasiya edək. Bunu etmək üçün hibernate.cfg.xml faylı yaradın:

    <?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>
Xüsusiyyətlərin təsviri :
  1. hibernate.dialekt seçdiyimiz DBMS-nin dialektidir.
  2. hibernate.connection.driver_class - DB-nin sürücü sinfi.
  3. hibernate.connection.url - DB-nin utl. Siz onu DB-ni konfiqurasiya etdiyimiz ilk nöqtədən götürə bilərsiniz.
  4. hibernate.connection.username - DB istifadəçi adı.
  5. hibernate.connection.password — DB istifadəçi parolu.
  6. hibernate.hbm2ddl.auto - cədvəl yaratmağın qurulması. Əgər yenilənirsə, o, artıq yaradılıbsa, yaratmır, ancaq onu yeniləyir.
  7. hibernate.show_sql - DB sorğularının göstərilib-göstərilməməsi.
  8. hibernate.format_sql - DB sorğularının formatlaşdırılıb-formatlanmayacağı. Əks təqdirdə, hamısı bir xəttdə olacaq. Mən onu yandırmağı məsləhət görürəm.
  9. hibernate.use_sql_comments - DB sorğularını şərh edir. Əgər bu Insertdirsə, o zaman sorğunun Insert tipli olması barədə sorğunun üstündə şərh yazılır.
  10. hibernate.generate_statistics - qeydlər yaradır. Girişi maksimum dərəcədə qurmağı tövsiyə edirəm və tövsiyə edirəm. Qeydləri oxumaq ORM ilə düzgün işləmək şansınızı artıracaq.
  11. hibernate.jdbc.batch_size — Maksimum toplu ölçüsü.
  12. hibernate.jdbc.fetch_size — Maksimum gətirmə ölçüsü.
  13. hibernate.order_inserts - dinamik əlavələrə icazə verir.
  14. hibernate.order_updates - Dinamik yeniləmələrə imkan verir.
  15. hibernate.jdbc.batch_versioned_data - paketləşdirməyə imkan verir. DBMS-ə baxın: hamı bunu dəstəkləmir.
  16. Xəritəçəkmə sinfi - bizim qurumlarımız olan siniflər. Hər şeyi sadalamaq lazımdır.
  1. İndi bizim mahiyyətimiz müəyyənləşməlidir. Bunu əzmkarlıq tabında yoxlaya bilərik:

    JPA Entities and DB Relationships - 11

    Nəticə:

    JPA Entities and DB Relationships - 12
  2. Biz həmçinin təyin datasını konfiqurasiya etməliyik:

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

    Nəticələr: Biz Birə Bir Xəritəçəkmə etdik. Material yalnız məlumat məqsədi daşıyır, təfərrüatlar istinadlardadır.

Bir-çox əlaqə

Filialın linki burada . Artıq çox uzun olduğu üçün kodu məqalədə yerləşdirməyəcəyəm. GitHub-da bütün koda baxırıq.
  1. İnisializasiya skriptinin icrası nəticəsində aşağıdakıları əldə edirik:

    JPA Entities and DB Relationships - 15

    Əvvəlki cədvəllə fərq hiss edirsinizmi?

  2. Diaqram:

    JPA Entities and DB Relationships - 16

    Bir-çox əlaqə - bir müəllifin bir neçə kitabı ola bilər. Sol obyekt bir və ya daha çox sağa uyğun gəlir.

  3. Xəritəçəkmədəki fərq annotasiyalarda və sahələrdə olacaq:

    Müəllif sinfində sahə görünür :

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "author")
    private Set<Book> books;

    Artıq bir dəstdir, çünki bir neçə kitabımız ola bilər. @OneToMany münasibət növü haqqında danışır. FetchType.Lazy deyir ki, əgər sorğuda göstərilməyibsə, kitabların bütün siyahısını yükləməyimiz lazım deyil. Onu da qeyd etmək lazımdır ki, bu sahə toString-ə əlavə oluna bilməz, əks halda StackOverflowError-u çəkməyə başlayacağıq. Mənim sevimli Lombokum bununla məşğul olur:

    @ToString(exclude = "books")

    Kitab sinfində biz Çoxdan Birə rəy veririk:

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "AUTHOR_ID", nullable = false)
    private Author author;

    Buradan belə nəticəyə gəlirik ki, Birdən Çoxa Çoxdan Birə və əksinə güzgü şəklidir. Qeyd etmək lazımdır ki, Hibernate iki istiqamətli kommunikasiyalar haqqında heç nə bilmir. Onun üçün bunlar iki fərqli əlaqədir: biri bir istiqamətdə, digəri əks istiqamətdə.

  4. hibernate.cfg.xml faylında çox şey dəyişməyib .

  5. Davamlılıq:

    JPA Entities and DB Relationships - 17

Çox-bir əlaqə

Çoxdan Birə, Birdən Çoxa güzgü görüntüsü olduğundan, fərqlər az olacaq. Filialın linki burada .
  1. İnisializasiya skriptinin icrası nəticəsində aşağıdakı nəticəni əldə edirik:

    JPA Entities and DB Relationships - 18
  2. Diaqram:

    JPA Entities and DB Relationships - 19
  3. Xəritəçəkmədəki fərq annotasiyalarda və sahələrdə olacaq:

    Kitab sinfinə keçdiyi üçün Müəllif sinfində artıq dəst yoxdur .

  4. hibernate.cfg.xml

  5. Davamlılıq:

    JPA Entities and DB Relationships - 20

Çoxdan Çoxa Münasibət

Ən maraqlı münasibətə keçək. Bu münasibət bütün ədəb və ədəbsizlik qaydalarına görə əlavə cədvəl vasitəsilə yaradılır. Lakin bu cədvəl bir varlıq deyil. Maraqlıdır, hə? Gəlin bu zəhmətə nəzər salaq. Filialın linki burada .
  1. İnisiallaşdırma skriptinə baxın , burada əlavə HAS cədvəli görünür. Biz müəllif-kitab kimi bir şey alırıq.

    Skriptin icrası nəticəsində aşağıdakı cədvəlləri alacağıq:

    JPA Entities and DB Relationships - 21
  2. Diaqram:

    JPA Entities and DB Relationships - 22

    Bizim nümunəmizdə belə çıxır ki, bir kitabın çoxlu müəllifi ola bilər, müəllifin də çoxlu kitabı ola bilər. Onlar üst-üstə düşə bilər.

  3. Xəritəçəkmə siniflərinin siniflər daxilində dəstləri olacaq. Amma dediyim kimi, HAS cədvəli bir varlıq deyil.

    Müəllif sinfi :

    @ManyToMany
    @JoinTable(name = "HAS",
            joinColumns = @JoinColumn(name = "AUTHOR_ID", referencedColumnName = "ID"),
            inverseJoinColumns = @JoinColumn(name = "BOOK_ID", referencedColumnName = "ID")
    )
    private Set<Book> books;

    @ManyToMany bir əlaqə növüdür.

    @JoinTable - atributu əlavə HAS cədvəli ilə birləşdirən məhz budur. Orada iki obyektin əsas açarlarına işarə edəcək iki atribut təyin edirik.

    Kitab sinfi :

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "books")
    private Set<Author> authors;

    Burada FetchType və xəritə üçün istifadə edəcəyimiz sahəni göstəririk.

  4. Bizim hibernate.cfg.xml yenə dəyişməz qaldı (hər filial üçün yeni DB yaratdığımızı nəzərə almıram).

  5. Davamlılıq:

    JPA Entities and DB Relationships - 23

Debrifinq

Beləliklə, biz DB əlaqələrinin növlərini səthi şəkildə araşdırdıq və onların ORM modelində necə həyata keçiriləcəyini anladıq. Bütün əlaqələri nümayiş etdirən bir sınaq layihəsi yazdıq və hibernate / jpa-nın necə konfiqurasiya olunacağını anladıq. vay.

faydalı bağlantılar

Əvvəlki məqalələrim: PS Mətndə səhvlər və çatışmazlıqlar ola bilər. PPS Müəllif bu məqaləni yazarkən qəribə bir şey çəkdi. Diqqətinizə görə təşəkkürlər!
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION