JavaRush /Java blogi /Random-UZ /JPA ob'ektlari va ma'lumotlar bazasi munosabatlari
Nikita Koliadin
Daraja
Днепр

JPA ob'ektlari va ma'lumotlar bazasi munosabatlari

Guruhda nashr etilgan

JPA ob'ektlari va ma'lumotlar bazasi bilan aloqalar

Xayrli kun, hamkasblar!
JPA ob'ektlari va ma'lumotlar bazasi bilan aloqalar - 1
Ushbu material ma'lumotlar bazalarini tashkil etish (keyingi o'rinlarda oddiygina DB - "Ma'lumotlar bazasi"), Ob'ekt-nisbiy xaritalash (keyingi o'rinlarda oddiygina ORM ) qanday ishlashi haqida minimal ma'lumotga ega bo'lganlar va Hibernate / JPA kabi uni amalga oshirish uchun mo'ljallangan. . Agar siz bu bilan tanish bo'lmasangiz, men sizga JDBC dan boshlashingizni maslahat beraman va shundan keyingina ORM modeliga o'ting. Men sizni ogohlantirdim va ushbu maqolani to'g'ri tayyorgarliksiz o'qib chiqqandan keyin sizning ruhiyatingiz uchun javobgar emasman! :) Keling, hamma narsani tartibda hal qilishni boshlaylik. Birinchidan, biz nazariyani biroz o'rganamiz, faqat bir oz. Ikkinchidan, biz buni hamma uchun sevimli Java-da qanday qilishni aniqlaymiz. Shuningdek, biz siz bilan mavzu bo'yicha tushunchamizni mustahkamlaydigan va xaritalash QANDAY amalga oshirilishi kerakligi uchun shablon bo'lib xizmat qiladigan loyiha varaqini yozamiz . Shunday qilib, qilaylik!

Entity nima?

Ob'ekt - bu atributlarga (eshiklar, G'ildiraklar , dvigatel ) ega bo'lgan haqiqiy hayotdagi ob'ekt (masalan, avtomobil) . JB ob'ekti: Bu holda, bizning ob'ektimiz JBda saqlanadi, hamma narsa oddiy. Nima uchun va qanday qilib mashinani ma'lumotlar bazasiga joylashtiramiz - keyinroq ko'rib chiqamiz.

JB aloqalari nima?

Uzoq vaqt oldin, uzoq qirollikda relyatsion ma'lumotlar bazasi yaratilgan . Ushbu ma'lumotlar bazasida ma'lumotlar jadval shaklida taqdim etilgan. Ammo Shrekdan kelgan eshak uchun bu jadvallarni o'zaro bog'lash mexanizmini yaratish kerakligi ham aniq edi . Natijada, 4 ma'lumotlar bazasi munosabatlari paydo bo'ldi :
  1. Birga-bir
  2. Birdan ko'pga
  3. Ko'pdan birga
  4. Ko'pdan ko'pga
Agar bularning barchasini birinchi marta ko'rayotgan bo'lsangiz, men sizni yana ogohlantiraman - bu yomonlashadi: sayr qilish haqida o'ylang. Biz ushbu munosabatlarning barchasini misol yordamida tahlil qilamiz va ular orasidagi farqni tushunamiz.

Qo'rqinchli misol

Bizda 5 ta filialga ega bo'lgan bitta loyiha bo'ladi: master, u erda loyiha tavsifi va har bir JB aloqasi uchun 1 ta filial. Har bir filialda ma'lumotlar bazasini yaratish va uni test ma'lumotlari bilan to'ldirish uchun SQL skriptlari, shuningdek izohli xaritalash bilan Entity klassi mavjud. Har bir filial uchun Hibernate konfiguratsiya fayli ham bo'ladi. Men bulutli ma'lumotlar bazasi yoki tashqi ma'lumotlar bazasining individual jihatlari bilan chalg'imaslik uchun loyiha uchun H2 o'rnatilgan ma'lumotlar bazasidan foydalanaman . Havola bo'yicha H2 DB ni changyutgichingizga o'rnating. Men har bir bosqichni 1 ta filialda tasvirlab beraman, qolganlari faqat asosiy fikrlardir. Oxirida biz xulosa qilamiz. Bor. Bu mening loyihamning asosiy bo'limiga havola.

Yakkama-yakka munosabat

Bu yerda filialga havola .
  1. Loyihamizga H2 DB ni ulashimiz kerak. Bu erda biz JB va boshqa narsalar bilan qulay ishlash uchun Ultimate IDEA kerakligini ta'kidlashimiz kerak. Agar sizda allaqachon mavjud bo'lsa, to'g'ridan-to'g'ri JB ulanishiga o'ting. Ma'lumotlar bazasi yorlig'iga o'ting va skrinshotda bo'lgani kabi bajaring:

    JPA Entities and DB Relationships - 2

    Keyinchalik biz JB sozlamalariga o'tamiz. Siz o'z ma'lumotlaringizni va hatto DBMSni kiritishingiz mumkin; Takrorlayman, men H2 DB dan soddalik uchun foydalanaman.

    JPA Entities and DB Relationships - 3

    Keyinchalik, sxemani o'rnatamiz. Bu qadam ixtiyoriy, lekin JBda bir nechta sxema bo'lsa tavsiya etiladi.

    JPA Entities and DB Relationships - 4

    Sozlamalarni qo'llang va oxirida biz shunga o'xshash narsani olamiz:

    JPA Entities and DB Relationships - 5
  2. Biz ma'lumotlar bazasini yaratdik va IDEA-dan unga kirishni sozladik. Endi siz unda jadvallar yaratishingiz va uni ba'zi ma'lumotlar bilan to'ldirishingiz kerak. Masalan, men ikkita ob'ektni olaman: Muallif va Kitob. Kitobning muallifi bo'lishi mumkin, bir nechta muallif bo'lishi mumkin yoki bitta bo'lmasligi mumkin. Ushbu misolda biz barcha turdagi ulanishlarni yaratamiz. Ammo bu nuqtada - Yakka-yakka munosabatlar. Keling, ma'lumotlar bazasi jadvallarini yaratadigan tegishli skriptni yarataylik :

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

    Va keling, uni bajaramiz:

    JPA Entities and DB Relationships - 6

    Konsolda bajarilish natijasi:

    JPA Entities and DB Relationships - 7

    JBdagi natija:

    JPA Entities and DB Relationships - 8
  3. Keling, jadvallarimizning diagrammasini ko'rib chiqaylik. Buning uchun bizning ma'lumotlar bazasida RMB:

    JPA Entities and DB Relationships - 9

    Natija:

    JPA Entities and DB Relationships - 10

    UML diagrammasida biz barcha asosiy kalitlarni va xorijiy kalitlarni ko'rishimiz mumkin, shuningdek, jadvallarimiz orasidagi aloqani ko'ramiz.

  4. Keling, ma'lumotlar bazasini test ma'lumotlari bilan to'ldiradigan skriptni yozaylik:

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

    Aytmoqchimanki, nima bo'ladi? Bir jadvalning ob'ekti boshqa bir ob'ekt bilan bog'liq bo'lsa (yoki BOOK_IDdan NOT NULL o'chirilgan bo'lsa, umuman bog'liq bo'lmasa) "Birga-bir" munosabat kerak bo'ladi. Bizning misolimizda bitta kitobda bitta muallif bo'lishi kerak. Boshqa yo'l yo'q.

  5. Endi eng qiziq narsa Java sinfini JB ob'ektlari bilan qanday ulash mumkin? Juda oddiy. Keling, Kitob va Muallif ikkita sinf yarataylik. Misol yordamida men 1-sinfni va asosiy aloqa sohalarini tahlil qilaman. Misol tariqasida Author sinfini olaylik :

    @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;
    }
Keling, buni tartibda aniqlaymiz:
  1. Sinfdagi barcha maydonlar JB ob'ektining atributlarini takrorlaydi.
  2. @Data ( Lombok dan ) aytadiki, har bir maydon uchun oluvchi va sozlagich yaratiladi, teng, xeshkod bekor qilinadi va toString usuli yaratiladi.
  3. @Entity , berilgan sinf ob'ekt ekanligini va JB ob'ekti bilan bog'langanligini aytadi.
  4. @DynamicInsert va @DynamicUpdate ma'lumotlar bazasida dinamik qo'shimchalar va yangilanishlar amalga oshirilishini aytadi. Bular chuqurroq Kutish rejimi sozlamalari bo‘lib, ular siz uchun TO‘G‘ri to‘plamga ega bo‘lishingiz uchun foydali bo‘ladi.
  5. @Table (nom = "AUTHOR") Book sinfini DB AUTHOR jadvaliga bog'laydi.
  6. @Id bu maydon asosiy kalit ekanligini aytadi.
  7. @GeneratedValue (strategiya = GenerationType.IDENTITY) – asosiy kalit yaratish strategiyasi.
  8. @Column (nom = "ID", null = noto'g'ri) maydonni JB atributi bilan bog'laydi va shuningdek, berilgan ma'lumotlar bazasi maydoni null bo'lmasligini aytadi. Bu ob'ektlardan jadvallarni yaratishda ham foydalidir. Loyihamizni qanday yaratganimizga teskari jarayon, bu birlik testlari uchun test ma'lumotlar bazasida kerak.
  9. @OneToOne , berilgan maydon Yakkama-yakka munosabatlar maydoni ekanligini aytadi.
  10. @JoinColumn (ism = "BOOK_ID", noyob = rost, null = noto'g'ri) - BOOK_ID ustuni yaratiladi, u noyob va null emas.
Orqa tomonda ( Kitob sinfida ) biz ham Yakkama-yakka ulanishni amalga oshirishimiz va xaritalash sodir bo'lgan maydonni ko'rsatishimiz kerak. @OneToOne(mappedBy = "book") - bu misolda bu Author sinfining kitob maydoni. JPA ularni o'zi bog'laydi. Bir qarashda, izohlar chalkashdek tuyulishi mumkin, lekin aslida bu juda qulay va tajriba bilan siz ularni o'ylamasdan avtomatik ravishda qo'shasiz.
  1. Endi kutish rejimini sozlaymiz. Buning uchun hibernate.cfg.xml faylini yarating:

    <?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>
Xususiyatlarning tavsifi :
  1. hibernate.dialect biz tanlagan DBMS dialektidir.
  2. hibernate.connection.driver_class — Maʼlumotlar bazasining haydovchilar klassi.
  3. hibernate.connection.url - bizning JB utl. Siz uni JBni sozlagan birinchi nuqtadan olishingiz mumkin.
  4. hibernate.connection.username - JB foydalanuvchi nomi.
  5. hibernate.connection.password — JB foydalanuvchi paroli.
  6. hibernate.hbm2ddl.auto - jadval yaratishni sozlash. Agar yangilangan bo'lsa, u allaqachon yaratilgan bo'lsa, yaratmaydi, faqat uni yangilaydi.
  7. hibernate.show_sql - ma'lumotlar bazasi so'rovlarini ko'rsatish kerakmi.
  8. hibernate.format_sql - ma'lumotlar bazasi so'rovlarini formatlash kerakmi. Agar yo'q bo'lsa, unda ularning barchasi bitta chiziqda bo'ladi. Men uni yoqishni tavsiya qilaman.
  9. hibernate.use_sql_comments - ma'lumotlar bazasi so'rovlarini sharhlaydi. Agar bu Insert bo'lsa, so'rovning Insert turiga tegishli ekanligi haqidagi so'rov ustiga izoh yoziladi.
  10. hibernate.generate_statistics - jurnallarni yaratadi. Men ro'yxatga olishni maksimal darajada sozlashni tavsiya qilaman va tavsiya qilaman. Jurnallarni o'qish ORM bilan to'g'ri ishlash imkoniyatingizni oshiradi.
  11. hibernate.jdbc.batch_size - Maksimal to'plam hajmi.
  12. hibernate.jdbc.fetch_size — Maksimal yuklash hajmi.
  13. hibernate.order_inserts - dinamik qo'shimchalarga ruxsat beradi.
  14. hibernate.order_updates - dinamik yangilanishlarga ruxsat beradi.
  15. hibernate.jdbc.batch_versioned_data - to'plamga ruxsat beradi. DBMSga qarang: hamma ham buni qo'llab-quvvatlamaydi.
  16. xaritalash sinfi - bizning ob'ektlarimiz bo'lgan sinflar. Hamma narsa ro'yxatga olinishi kerak.
  1. Endi bizning mohiyatimiz aniqlanishi kerak. Buni qat'iylik yorlig'ida tekshirishimiz mumkin:

    JPA Entities and DB Relationships - 11

    Natija:

    JPA Entities and DB Relationships - 12
  2. Shuningdek, biz ma'lumotlarni tayinlashni sozlashimiz kerak:

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

    Natijalar: Biz birma-bir xaritalashni amalga oshirdik. Material faqat ma'lumot uchun mo'ljallangan, tafsilotlar ma'lumotnomalarda keltirilgan.

Birdan ko'pga munosabat

Bu yerda filialga havola . Kodni endi maqolaga joylashtirmayman, chunki u juda uzun. Biz GitHub-dagi barcha kodlarni ko'rib chiqamiz.
  1. Initsializatsiya skriptini bajarish natijasida biz quyidagilarni olamiz:

    JPA Entities and DB Relationships - 15

    Oldingi jadvaldan farqni his qilyapsizmi?

  2. Diagramma:

    JPA Entities and DB Relationships - 16

    Birga-ko'p munosabatlar - bitta muallifning bir nechta kitoblari bo'lishi mumkin. Chap ob'ekt bir yoki bir nechta o'ngga mos keladi.

  3. Xaritalashdagi farq izohlar va maydonlarda bo'ladi:

    Muallif sinfida maydon paydo bo'ladi :

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

    Bu allaqachon to'plam, chunki bizda bir nechta kitoblar bo'lishi mumkin. @OneToMany munosabat turi haqida gapiradi. FetchType.Lazy, agar so'rovda ko'rsatilmagan bo'lsa, kitoblarning butun ro'yxatini yuklashimiz shart emasligini aytadi. Shuni ham aytish kerakki, bu maydonni toString-ga qo'shib bo'lmaydi, aks holda biz StackOverflowError-ni chekishni boshlaymiz. Mening sevimli Lombokim bunga g'amxo'rlik qiladi:

    @ToString(exclude = "books")

    “Kitob” darsida biz “Ko‘pdan birga” fikr-mulohazalarini qilamiz:

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

    Bu erda biz "Birdan ko'pga" "Ko'pdan birga" ning ko'zgu tasviri va aksincha degan xulosaga keldik. Shuni ta'kidlash kerakki, Hibernate ikki tomonlama aloqalar haqida hech narsa bilmaydi. Uning uchun bu ikki xil aloqa: biri bir yo'nalishda, ikkinchisi esa teskari yo'nalishda.

  4. hibernate.cfg.xml da ko'p narsa o'zgarmadi .

  5. Qat'iylik:

    JPA Entities and DB Relationships - 17

Ko'pdan-birga munosabatlar

"Ko'pdan birga" "Birdan ko'p" ning oyna tasviri bo'lgani uchun farqlar kam bo'ladi. Bu yerda filialga havola .
  1. Initsializatsiya skriptini bajarish natijasida biz quyidagi natijaga erishamiz:

    JPA Entities and DB Relationships - 18
  2. Diagramma:

    JPA Entities and DB Relationships - 19
  3. Xaritalashdagi farq izohlar va maydonlarda bo'ladi:

    Muallif sinfida endi to'plam yo'q, chunki u Kitob sinfiga o'tgan .

  4. hibernate.cfg.xml

  5. Qat'iylik:

    JPA Entities and DB Relationships - 20

Ko'pdan ko'pga munosabat

Keling, eng qiziqarli munosabatlarga o'tamiz. Bu munosabatlar, barcha odob va odobsizlik qoidalariga ko'ra, qo'shimcha jadval orqali yaratiladi. Ammo bu jadval ob'ekt emas. Qiziqarli, to'g'rimi? Keling, bu ahmoqni ko'rib chiqaylik. Bu yerda filialga havola .
  1. Boshlash skriptiga qarang , bu erda qo'shimcha HAS jadvali paydo bo'ladi. Biz muallifning kitobi kabi narsalarni olamiz.

    Skriptni bajarish natijasida biz quyidagi jadvallarni olamiz:

    JPA Entities and DB Relationships - 21
  2. Diagramma:

    JPA Entities and DB Relationships - 22

    Bizning misolimizda ma’lum bo‘lishicha, kitobning muallifi ko‘p bo‘lishi mumkin, muallifning esa ko‘p kitobi bo‘lishi mumkin. Ular bir-birining ustiga chiqishi mumkin.

  3. Xaritalash sinflari sinflar ichida to'plamlarga ega bo'ladi. Lekin aytganimdek, HAS jadvali ob'ekt emas.

    Muallif sinfi :

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

    @ManyToMany - bu munosabatlar turi.

    @JoinTable - bu atributni qo'shimcha HAS jadvali bilan bog'laydigan narsa. Unda biz ikkita ob'ektning asosiy kalitlarini ko'rsatadigan ikkita atributni belgilaymiz.

    Kitob sinfi :

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

    Bu erda biz FetchType va xaritalash uchun foydalanadigan maydonni ko'rsatamiz.

  4. Bizning hibernate.cfg.xml yana o'zgarishsiz qoldi (har bir filial uchun yangi ma'lumotlar bazasi yaratganimizni hisobga olmayman).

  5. Qat'iylik:

    JPA Entities and DB Relationships - 23

Debrifing

Shunday qilib, biz JB munosabatlarining turlarini yuzaki ko'rib chiqdik va ularni ORM modelida qanday amalga oshirishni aniqladik. Biz barcha ulanishlarni ko'rsatadigan sinov loyihasini yozdik va hibernate / jpa ni qanday sozlashni aniqladik. Voy.

foydali havolalar

Mening oldingi maqolalarim: PS Matnda xato va kamchiliklar bo'lishi mumkin. PPS Ushbu maqolani yozayotganda muallif g'alati bir narsa chekdi. E'tiboringiz uchun rahmat!
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION