JavaRush /Java blogi /Random-UZ /JPA: Texnologiyani joriy etish
Viacheslav
Daraja

JPA: Texnologiyani joriy etish

Guruhda nashr etilgan
Zamonaviy rivojlanish dunyosi hayotni osonlashtirish uchun mo'ljallangan turli xil xususiyatlarga to'la. Asboblarni bilib, siz to'g'ri tanlashingiz mumkin. Bilmasdan, hayotingizni qiyinlashtirasiz. Ushbu sharh JPA - Java Persistence API kontseptsiyasi ustidan maxfiylik pardasini olib tashlaydi. Umid qilamanki, o'qiganingizdan so'ng siz ushbu sirli dunyoga yanada chuqurroq sho'ng'ishni xohlaysiz.
JPA : Texnologiyaga kirish - 1

Kirish

Ma'lumki, dasturlarning asosiy vazifalaridan biri ma'lumotlarni saqlash va qayta ishlashdir. Qadimgi yaxshi kunlarda odamlar shunchaki ma'lumotlarni fayllarda saqlashgan. Ammo bir vaqtning o'zida o'qish va tahrirlash uchun ruxsat zarur bo'lishi bilanoq, yuk bo'lganda (ya'ni, bir vaqtning o'zida bir nechta so'rovlar keladi), ma'lumotlarni oddiygina fayllarda saqlash muammoga aylanadi. Ma'lumotlar bazasi qanday muammolarni hal qilishi va qanday qilib echilishi haqida ko'proq ma'lumot olish uchun sizga " Ma'lumotlar bazalari qanday tuzilgan " maqolasini o'qishni maslahat beraman . Bu shuni anglatadiki, biz ma'lumotlarimizni ma'lumotlar bazasida saqlashga qaror qildik. Uzoq vaqt davomida Java JDBC API (The Java Database Connectivity) yordamida maʼlumotlar bazalari bilan ishlay oldi. JDBC haqida ko'proq ma'lumotni bu erda o'qishingiz mumkin: " JDBC yoki hammasi qaerdan boshlanadi ". Ammo vaqt o'tdi va ishlab chiquvchilar har safar ma'lumotlar bazasida Java ob'ektlarini saqlash va aksincha, Java ob'ektlarini yaratish uchun bir xil turdagi va keraksiz "xizmat ko'rsatish" kodini (Boilerplate kodi deb ataladi) yozish zarurligiga duch kelishdi. ma'lumotlar bazasi. Va keyin, bu muammolarni hal qilish uchun ORM kabi tushuncha paydo bo'ldi. ORM - Ob'ekt bilan bog'liq xaritalash yoki rus tiliga tarjima qilingan ob'ekt bilan bog'liq xaritalash. Bu ma'lumotlar bazalarini ob'ektga yo'naltirilgan dasturlash tillari tushunchalari bilan bog'laydigan dasturlash texnologiyasidir. Soddalashtirish uchun, ORM Java ob'ektlari va ma'lumotlar bazasidagi yozuvlar o'rtasidagi bog'liqlikdir: JPA: Texnologiyaga kirish - 2ORM mohiyatan Java ob'ekti ma'lumotlar bazasida ma'lumotlar sifatida taqdim etilishi mumkin bo'lgan tushunchadir (va aksincha). U JPA spetsifikatsiyasi - Java Persistence API ko'rinishida mujassamlangan. Spetsifikatsiya allaqachon ushbu kontseptsiyani ifodalovchi Java API tavsifidir. Spetsifikatsiya bizga ORM kontseptsiyasiga muvofiq ishlash uchun qanday vositalar bilan ta'minlanishi kerakligini (ya'ni, qanday interfeyslar orqali ishlashimiz mumkinligini) aytadi. Va bu mablag'lardan qanday foydalanish kerak. Spetsifikatsiya asboblarni amalga oshirishni tavsiflamaydi. Bu bitta spetsifikatsiya uchun turli ilovalardan foydalanish imkonini beradi. Siz uni soddalashtirishingiz va spetsifikatsiya API tavsifi ekanligini aytishingiz mumkin. JPA spetsifikatsiyasining matnini Oracle veb-saytida topish mumkin: " JSR 338: JavaTM Persistence API ". Shuning uchun, JPA-dan foydalanish uchun biz texnologiyadan foydalanamiz. JPA ilovalari JPA Provayderlari deb ham ataladi. Eng mashhur JPA ilovalaridan biri bu Hibernate . Shuning uchun men buni ko'rib chiqishni taklif qilaman.
JPA: Texnologiyaga kirish - 3

Loyiha yaratish

JPA Java haqida bo'lgani uchun bizga Java loyihasi kerak bo'ladi. Biz o'zimiz katalog tuzilmasini qo'lda yaratishimiz va kerakli kutubxonalarni o'zimiz qo'shishimiz mumkin edi. Ammo loyihalarni yig'ishni avtomatlashtirish tizimlaridan foydalanish ancha qulayroq va to'g'ri (ya'ni, aslida bu biz uchun loyihalarni yig'ishni boshqaradigan dastur. Kataloglar yaratish, sinf yo'liga kerakli kutubxonalarni qo'shish va h.k. .). Shunday tizimlardan biri Gradle. Gradle haqida ko'proq ma'lumotni bu erda o'qishingiz mumkin: " Gradle haqida qisqacha kirish ". Ma'lumki, Gradle funksionalligi (ya'ni, u qila oladigan narsalar) turli Gradle plaginlari yordamida amalga oshiriladi. Keling, Gradle va " Gradle Build Init Plugin " plaginidan foydalanamiz . Keling, buyruqni bajaramiz:

gradle init --type java-application
Gradle biz uchun kerakli katalog tuzilmasini amalga oshiradi va qurilish skriptida loyihaning asosiy deklarativ tavsifini yaratadi build.gradle. Shunday qilib, bizda ariza bor. Biz ilovamiz bilan nimani tasvirlash yoki modellashtirish haqida o'ylashimiz kerak. Keling, ba'zi modellashtirish vositalaridan foydalanamiz, masalan: app.quickdatabasediagrams.com JPA: Texnologiyaga kirish - 4 Bu erda biz ta'riflagan narsa bizning "domen modelimiz" ekanligini aytish kerak. Domen - bu "mavzu sohasi". Umuman olganda, domen lotincha "egalik" degan ma'noni anglatadi. Oʻrta asrlarda qirollar yoki feodallarga tegishli boʻlgan hududlar shunday nomlangan. Va frantsuz tilida bu "domen" so'ziga aylandi, bu shunchaki "maydon" deb tarjima qilinadi. Shunday qilib, biz "domen modelimiz" = "mavzu modeli" ni tasvirlab berdik. Ushbu modelning har bir elementi haqiqiy hayotdan qandaydir "mohiyat" dir. Bizning holatlarimizda bu ob'ektlar: Turkum ( Category), Mavzu ( Topic). Keling, ob'ektlar uchun alohida paket yarataylik, masalan, nom modeli bilan. Keling, u erda ob'ektlarni tavsiflovchi Java sinflarini qo'shamiz. Java kodida bunday ob'ektlar oddiy POJO bo'lib , u quyidagicha ko'rinishi mumkin:
public class Category {
    private Long id;
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
Keling, sinf tarkibini ko'chiramiz va analogiya bo'yicha sinf yaratamiz Topic. U faqat o'zi tegishli bo'lgan toifa haqida bilgan narsasi bilan farq qiladi. TopicShuning uchun sinfga kategoriya maydoni va u bilan ishlash usullarini qo'shamiz :
private Category category;

public Category getCategory() {
	return category;
}

public void setCategory(Category category) {
	this.category = category;
}
Endi bizda o'z domen modeliga ega Java ilovasi mavjud. Endi JPA loyihasiga ulanishni boshlash vaqti keldi.
JPA: Texnologiyaga kirish - 5

JPA qo'shish

Shunday qilib, biz eslaganimizdek, JPA ma'lumotlar bazasida biror narsani saqlashimizni anglatadi. Shuning uchun bizga ma'lumotlar bazasi kerak. Loyihamizda ma'lumotlar bazasi ulanishidan foydalanish uchun biz ma'lumotlar bazasiga ulanish uchun bog'liqlik kutubxonasini qo'shishimiz kerak. Esda tutganimizdek, biz Gradle-dan foydalanganmiz, u biz uchun qurilish skriptini yaratdi build.gradle. Unda biz loyihamizga kerak bo'lgan bog'liqliklarni tasvirlab beramiz. Bog'liqlar - bu bizning kodimiz ishlamaydigan kutubxonalar. Keling, ma'lumotlar bazasiga ulanishga bog'liqlik tavsifidan boshlaylik. Agar biz JDBC bilan ishlagan bo'lsak, buni xuddi shunday qilamiz:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
Endi bizda ma'lumotlar bazasi mavjud. Endi biz ilovamizga Java obyektlarimizni ma'lumotlar bazasi tushunchalariga (Java'dan SQLgacha) solishtirish uchun mas'ul bo'lgan qatlamni qo'shishimiz mumkin. Esda tutganimizdek, biz buning uchun Hibernate deb nomlangan JPA spetsifikatsiyasining amalga oshirilishidan foydalanmoqchimiz:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
	implementation 'org.hibernate:hibernate-core:5.4.2.Final'
Endi biz JPA ni sozlashimiz kerak. Agar biz spetsifikatsiyani va "8.1 Doimiylik birligi" bo'limini o'qib chiqsak, biz Persistent birligi konfiguratsiyalar, metama'lumotlar va ob'ektlarning qandaydir kombinatsiyasi ekanligini bilib olamiz. Va JPA ishlashi uchun konfiguratsiya faylida kamida bitta Doimiylik Birligini tavsiflash kerak, bu persistence.xml. Uning joylashuvi "8.2 Persistence Unit Packaging" spetsifikatsiya bo'limida tasvirlangan. Ushbu bo'limga ko'ra, agar bizda Java SE muhiti bo'lsa, uni META-INF katalogining ildiziga qo'yishimiz kerak.
JPA: Texnologiyaga kirish - 6
Keling, " " bobidagi JPA spetsifikatsiyasida keltirilgan misoldan tarkibni ko'chirib olaylik 8.2.1 persistence.xml file:
<persistence>
	<persistence-unit name="JavaRush">
        <description>Persistence Unit For test</description>
        <class>hibernate.model.Category</class>
        <class>hibernate.model.Topic</class>
    </persistence-unit>
</persistence>
Lekin bu yetarli emas. JPA provayderimiz kimligini aytishimiz kerak, ya'ni. JPA spetsifikatsiyasini amalga oshiruvchi:
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
Endi sozlamalarni qo'shamiz ( properties). Ulardan ba'zilari (dan boshlab javax.persistence) standart JPA konfiguratsiyalari bo'lib, JPA spetsifikatsiyasida "8.2.1.9 xususiyatlari" bo'limida tasvirlangan. Ba'zi konfiguratsiyalar provayderga xosdir (bizning holimizda ular Jpa provayderi sifatida Kutish rejimiga ta'sir qiladi. Bizning sozlamalar blokimiz quyidagicha ko'rinadi:
<properties>
    <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
    <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1;MVCC=TRUE" />
    <property name="javax.persistence.jdbc.user" value="sa" />
    <property name="javax.persistence.jdbc.password" value="" />
    <property name="hibernate.show_sql" value="true" />
    <property name="hibernate.hbm2ddl.auto" value="create" />
</properties>
Endi bizda JPA-mos keladigan konfiguratsiya mavjud persistence.xml, JPA provayderi Hibernate va H2 ma'lumotlar bazasi mavjud, shuningdek, bizning domen modelimiz bo'lgan 2 ta sinf mavjud. Keling, nihoyat, bularning barchasini bajaraylik. Katalogda /test/javabizning Gradle birlik testlari uchun shablonni yaratdi va uni AppTest deb nomladi. Keling, undan foydalanaylik. JPA spetsifikatsiyasining "7.1 Doimiylik kontekstlari" bo'limida aytilganidek, JPA dunyosidagi ob'ektlar Doimiylik konteksti deb nomlangan bo'shliqda yashaydi. Lekin biz Persistence Context bilan bevosita ishlamaymiz. Buning uchun biz yoki "ob'ekt menejeri" dan foydalanamiz Entity Manager. U kontekst va u erda qanday shaxslar yashashi haqida biladi. Biz Entity Managerom bilan muloqot qilamiz. Keyin qolgan narsa buni qaerdan olishimiz mumkinligini tushunishdir Entity Manager? JPA spetsifikatsiyasining "7.2.2 Ilova tomonidan boshqariladigan ob'ekt menejerini olish" bo'limiga muvofiq biz dan foydalanishimiz kerak EntityManagerFactory. Shuning uchun, keling, JPA spetsifikatsiyasi bilan qurollanamiz va "7.3.2 Java SE muhitida ob'ekt menejeri zavodini olish" bo'limidan misol keltiramiz va uni oddiy birlik testi shaklida formatlaymiz:
@Test
public void shouldStartHibernate() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	EntityManager entityManager = emf.createEntityManager();
}
Bu test allaqachon xatoni ko'rsatadi "Notanish JPA persistence.xml XSD versiyasi". Buning sababi, persistence.xmlJPA spetsifikatsiyasida "8.3 persistence.xml sxemasi" bo'limida aytilganidek, foydalanish uchun sxemani to'g'ri belgilashingiz kerak:
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_2.xsd"
             version="2.2">
Bundan tashqari, elementlarning tartibi muhim ahamiyatga ega. Shuning uchun, providersinflarni ro'yxatga olishdan oldin uni ko'rsatish kerak. Shundan so'ng, test muvaffaqiyatli o'tadi. To'g'ridan-to'g'ri JPA ulanishini yakunladik. Davom etishdan oldin, qolgan testlar haqida o'ylab ko'raylik. Bizning har bir testimiz talab qiladi EntityManager. EntityManagerKeling , bajarilish boshida har bir testning o'ziga xos xususiyati borligiga ishonch hosil qilaylik . Bundan tashqari, biz ma'lumotlar bazasi har safar yangi bo'lishini xohlaymiz. Variantdan foydalanganimiz sababli inmemory, yopish kifoya EntityManagerFactory. Yaratish Factoryqimmat operatsiya. Ammo sinovlar uchun bu oqlanadi. JUnit sizga har bir testni bajarishdan oldin (oldin) va keyin (keyin) bajariladigan usullarni belgilash imkonini beradi:
public class AppTest {
    private EntityManager em;

    @Before
    public void init() {
        EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
        em = emf.createEntityManager();
    }

    @After
    public void close() {
        em.getEntityManagerFactory().close();
        em.close();
    }
Endi, har qanday testni o'tkazishdan oldin, yangisi yaratiladi EntityManagerFactory, bu yangi ma'lumotlar bazasini yaratishga olib keladi, chunki hibernate.hbm2ddl.automa'noga ega create. Va yangi zavoddan biz yangisini olamiz EntityManager.
JPA: Texnologiyaga kirish - 7

Ob'ektlar

Esda tutganimizdek, biz ilgari domen modelimizni tavsiflovchi sinflarni yaratgan edik. Biz allaqachon aytgan edik, bu bizning "mohiyatlarimiz". Bu biz boshqaradigan ob'ekt EntityManager. Kategoriyaning mohiyatini saqlash uchun oddiy test yozamiz:
@Test
public void shouldPersistCategory() {
	Category cat = new Category();
	cat.setTitle("new category");
	// JUnit обеспечит тест свежим EntityManager'ом
	em.persist(cat);
}
Ammo bu test darhol ishlamaydi, chunki ... Biz ob'ektlar nima ekanligini tushunishimizga yordam beradigan turli xil xatolarni olamiz:
  • Unknown entity: hibernate.model.Category
    CategoryNega Hibernate bu nima ekanligini tushunmaydi entity? Gap shundaki, ob'ektlar JPA standartiga muvofiq tavsiflanishi kerak. JPA spetsifikatsiyasining "2.1 Ob'ektlar klassi" bobida aytilganidek,
    ob'ektlar sinflari izoh bilan izohlanishi kerak .@Entity

  • No identifier specified for entity: hibernate.model.Category
    Tashkilotlar bitta yozuvni boshqasidan ajratish uchun ishlatilishi mumkin bo'lgan noyob identifikatorga ega bo'lishi kerak.
    JPA spetsifikatsiyasining "2.4 Asosiy kalitlar va ob'ekt identifikatori" bo'limiga ko'ra, "Har bir ob'ektda birlamchi kalit bo'lishi kerak", ya'ni. Har bir ob'ektda "asosiy kalit" bo'lishi kerak. Bunday asosiy kalit izoh bilan ko'rsatilishi kerak@Id

  • ids for this class must be manually assigned before calling save()
    ID biror joydan kelishi kerak. U qo'lda ko'rsatilishi yoki avtomatik ravishda olinishi mumkin.
    Shuning uchun, "11.2.3.3 GeneratedValue" va "11.1.20 GeneratedValue Izoh" boblarida ko'rsatilganidek, biz izohni belgilashimiz mumkin @GeneratedValue.

Shunday qilib, toifa sinfi ob'ekt bo'lishi uchun biz quyidagi o'zgarishlarni amalga oshirishimiz kerak:
@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;
Bundan tashqari, izoh @Idqaysi birini ishlatishni ko'rsatadi Access Type. Kirish turi haqida ko'proq JPA spetsifikatsiyasining "2.3 Kirish turi" bo'limida o'qishingiz mumkin. Qisqacha aytganda, chunki... biz @Idyuqorida maydonni ( field), keyin kirish turi standart bo'ladi field-based, emas property-based. Shuning uchun JPA provayderi qiymatlarni to'g'ridan-to'g'ri maydonlardan o'qiydi va saqlaydi. Agar biz @Idoluvchining ustiga joylashtirsak, u holda property-basedkirish foydalaniladi, ya'ni. oluvchi va sozlagich orqali. Sinovni o'tkazishda biz ma'lumotlar bazasiga qanday so'rovlar yuborilganligini ham ko'ramiz (variant tufayli hibernate.show_sql). Lekin saqlashda biz hech qanday 'sni ko'rmaymiz insert. Ma'lum bo'lishicha, biz aslida hech narsani saqlamaganmiz? JPA sizga quyidagi usul yordamida qat'iylik konteksti va ma'lumotlar bazasini sinxronlashtirish imkonini beradi flush:
entityManager.flush();
Ammo agar biz uni hozir bajarsak, xatoga duch kelamiz: hech qanday tranzaksiya bajarilmaydi . Va endi JPA tranzaktsiyalardan qanday foydalanishi haqida bilib olish vaqti keldi.
JPA: Texnologiyaga kirish - 8

JPA operatsiyalari

Esda tutganimizdek, JPA qat'iylik konteksti kontseptsiyasiga asoslanadi. Bu ob'ektlar yashaydigan joy. Va biz ob'ektlarni orqali boshqaramiz EntityManager. Buyruqni bajarganimizda persist, ob'ektni kontekstga joylashtiramiz. Aniqrog'i, biz EntityManagerbuni qilish kerakligini aytamiz. Ammo bu kontekst faqat ba'zi saqlash joyidir. U hatto ba'zan "birinchi darajadagi kesh" deb ataladi. Lekin u ma'lumotlar bazasiga ulanishi kerak. Ilgari xato bilan muvaffaqiyatsiz bo'lgan buyruq flushma'lumotlar bazasi bilan qat'iylik kontekstidagi ma'lumotlarni sinxronlashtiradi. Ammo bu transportni talab qiladi va bu transport tranzaksiyadir. JPAdagi operatsiyalar spetsifikatsiyaning "7.5 Nazorat qiluvchi operatsiyalar" bo'limida tasvirlangan. JPA-da tranzaktsiyalardan foydalanish uchun maxsus API mavjud:
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
Testlardan oldin va keyin ishlaydigan kodimizga tranzaksiya boshqaruvini qo'shishimiz kerak:
@Before
public void init() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	em = emf.createEntityManager();
	em.getTransaction().begin();
}
@After
public void close() {
	if (em.getTransaction().isActive()) {
		em.getTransaction().commit();
        }
	em.getEntityManagerFactory().close();
	em.close();
}
Qo'shgandan so'ng, biz qo'shish jurnalida SQLda ilgari bo'lmagan ifodani ko'ramiz:
JPA: Texnologiyaga kirish - 9
Tranzaktsiyada to'plangan o'zgarishlar EntityManagerma'lumotlar bazasida amalga oshirildi (tasdiqlandi va saqlangan). Keling, o'z mohiyatimizni topishga harakat qilaylik. Ob'ektni identifikatori bo'yicha qidirish uchun test yarataylik:
@Test
public void shouldFindCategory() {
	Category cat = new Category();
	cat.setTitle("test");
	em.persist(cat);
	Category result = em.find(Category.class, 1L);
	assertNotNull(result);
}
Bunday holda, biz avval saqlangan ob'ektni olamiz, lekin jurnalda SELECT so'rovlarini ko'rmaymiz. Va hamma narsa biz aytganlarimizga asoslanadi: "Shaxs menejeri, iltimos, menga ID=1 bo'lgan toifadagi ob'ektni toping." Va ob'ekt menejeri birinchi navbatda uning kontekstiga qaraydi (bir turdagi keshdan foydalanadi) va agar uni topa olmasa, u ma'lumotlar bazasiga kirishga ketadi. Identifikatorni 2 ga o'zgartirishga arziydi (bunday narsa yo'q, biz faqat 1 nusxani saqladik) va biz SELECTso'rov paydo bo'lishini ko'ramiz. Chunki kontekstda ob'ektlar topilmadi va EntityManagerma'lumotlar bazasi ob'ektni topishga harakat qilmoqda.Biz kontekstdagi ob'ekt holatini boshqarish uchun foydalanishimiz mumkin bo'lgan turli xil buyruqlar mavjud. Ob'ektning bir holatdan ikkinchi holatga o'tishi ob'ektning hayot aylanishi deb ataladi - lifecycle.
JPA: Texnologiyaga kirish - 10

Ob'ektning hayot aylanishi

Ob'ektlarning hayot aylanishi JPA spetsifikatsiyasida "3.2 Entity Instance hayotiy tsikli" bo'limida tasvirlangan. Chunki ob'ektlar kontekstda yashaydi va tomonidan nazorat qilinadi EntityManager, keyin ular sub'ektlar nazorat qilinadi, deyishadi, ya'ni. boshqargan. Keling, mavjudlik hayotining bosqichlarini ko'rib chiqaylik:
// 1. New or Transient (временный)
Category cat = new Category();
cat.setTitle("new category");
// 2. Managed or Persistent
entityManager.persist(cat);
// 3. Транзакция завершена, все сущности в контексте detached
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
// 4. Сущность изымаем из контекста, она становится detached
entityManager.detach(cat);
// 5. Сущность из detached можно снова сделать managed
Category managed = entityManager.merge(cat);
// 6. И можно сделать Removed. Интересно, что cat всё равно detached
entityManager.remove(managed);
Va uni birlashtirish uchun diagramma:
JPA: Texnologiyaga kirish - 11
JPA: Texnologiyaga kirish - 12

Xaritalash

JPA da biz ob'ektlarning bir-biri o'rtasidagi munosabatlarini tasvirlashimiz mumkin. Keling, domen modelimiz bilan shug'ullanganimizda, biz allaqachon ob'ektlarning bir-birlari o'rtasidagi munosabatlarini ko'rib chiqqanimizni eslaylik. Keyin biz quickdatabasediagrams.com resursidan foydalandik :
JPA: Texnologiyaga kirish - 13
Ob'ektlar o'rtasida aloqalarni o'rnatish xaritalash yoki assotsiatsiya (Association Mappings) deb ataladi. JPA yordamida tashkil etilishi mumkin bo'lgan uyushmalar turlari quyida keltirilgan:
JPA : Texnologiyaga kirish - 14
TopicKeling , mavzuni tavsiflovchi ob'ektni ko'rib chiqaylik . TopicUnga bo'lgan munosabat haqida nima deyishimiz mumkin Category? Ko'pchilik Topicbir toifaga tegishli bo'ladi. Shuning uchun bizga uyushma kerak ManyToOne. Keling, ushbu munosabatni JPAda ifodalaymiz:
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
Qaysi izohlarni qo'yish kerakligini eslab qolish uchun oxirgi qism yuqorida izoh ko'rsatilgan maydon uchun javobgar ekanligini yodda tutishingiz mumkin. ToOne- aniq misol. ToMany- to'plamlar. Endi bizning aloqamiz bir tomonlama. Keling, buni ikki tomonlama aloqaga aylantiraylik. Keling , ushbu toifaga kiritilgan Categoryhar bir kishi haqidagi bilimlarni qo'shaylik . TopicBu bilan tugashi kerak ToMany, chunki bizda ro'yxat bor Topic. Ya'ni, "Ko'p" mavzularga munosabat. Savol qoladi - OneToManyyoki ManyToMany:
JPA: Texnologiyaga kirish - 15
Xuddi shu mavzu bo'yicha yaxshi javobni bu erda o'qishingiz mumkin: " ORM oneToMany, manyToMany munosabatlarini men besh yoshdaman kabi tushuntiring ". Agar toifa mavzular bilan bog'liq bo'lsa ToMany, bu mavzularning har biri faqat bitta toifaga ega bo'lishi mumkin, keyin u bo'ladi One, aks holda Many. Shunday qilib, Categorybarcha mavzular ro'yxati quyidagicha ko'rinadi:
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "topic_id")
private Set<Topic> topics = new HashSet<>();
CategoryVa keling , barcha mavzular ro'yxatini olish uchun asosan oluvchi yozishni unutmang :
public Set<Topic> getTopics() {
	return this.topics;
}
Ikki tomonlama munosabatlarni avtomatik kuzatish juda qiyin narsa. Shuning uchun JPA bu mas'uliyatni ishlab chiquvchiga o'tkazadi. TopicBu biz uchun shuni anglatadiki, biz bilan ob'ekt munosabatlarini o'rnatganimizda Category, ma'lumotlar izchilligini o'zimiz ta'minlashimiz kerak. Bu oddiygina amalga oshiriladi:
public void setCategory(Category category) {
	category.getTopics().add(this);
	this.category = category;
}
Tekshirish uchun oddiy test yozamiz:
@Test
public void shouldPersistCategoryAndTopics() {
	Category cat = new Category();
	cat.setTitle("test");
	Topic topic = new Topic();
	topic.setTitle("topic");
	topic.setCategory(cat);
 	em.persist(cat);
}
Xarita yaratish butunlay alohida mavzu. Ushbu ko'rib chiqishning maqsadi bunga erishish usullarini tushunishdir. Bu yerda xaritalash haqida ko'proq o'qishingiz mumkin:
JPA : Texnologiyaga kirish - 16

JPQL

JPA qiziqarli vositani taqdim etadi - Java Persistence Query Language so'rovlari. Bu til SQL tiliga o'xshaydi, lekin SQL jadvallaridan ko'ra Java ob'ekt modelidan foydalanadi. Keling, bir misolni ko'rib chiqaylik:
@Test
public void shouldPerformQuery() {
	Category cat = new Category();
	cat.setTitle("query");
	em.persist(cat);
	Query query = em.createQuery("SELECT c from Category c WHERE c.title = 'query'");
 	assertNotNull(query.getSingleResult());
}
Ko'rib turganimizdek, so'rovda biz jadvalga Categoryemas, balki ob'ektga havoladan foydalandik. Va shuningdek, ushbu shaxs sohasida title. JPQL ko'plab foydali xususiyatlarni taqdim etadi va o'z maqolasiga loyiqdir. Batafsil ma'lumotni sharhda topishingiz mumkin:
JPA : Texnologiyaga kirish - 17

Criteria API

Va nihoyat, Criteria API-ga tegmoqchiman. JPA dinamik so'rovlar yaratish vositasini taqdim etadi. Criteria API dan foydalanishga misol:
@Test
public void shouldFindWithCriteriaAPI() {
	Category cat = new Category();
	em.persist(cat);
	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<Category> query = cb.createQuery(Category.class);
	Root<Category> c = query.from(Category.class);
	query.select(c);
	List<Category> resultList = em.createQuery(query).getResultList();
	assertEquals(1, resultList.size());
}
Bu misol " " so'rovini bajarishga teng SELECT c FROM Category c. Criteria API kuchli vositadir. Bu haqda ko'proq ma'lumotni bu yerda o'qishingiz mumkin:

Xulosa

Ko'rib turganimizdek, JPA juda ko'p xususiyatlar va vositalarni taqdim etadi. Ularning har biri tajriba va bilim talab qiladi. Hatto JPA tekshiruvi doirasida ham hamma narsani eslatib o'tishning iloji bo'lmadi, batafsil sho'ng'in haqida gapirmaslik kerak. Ammo umid qilamanki, uni o'qib chiqqandan so'ng, ORM va JPA nima ekanligi, ular qanday ishlashi va u bilan nima qilish mumkinligi aniq bo'ldi. Xo'sh, aperatif uchun men turli xil materiallarni taklif qilaman: #Viacheslav
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION