JavaRush /Java Blogu /Random-AZ /JPA: Texnologiyanın Təqdimatı
Viacheslav
Səviyyə

JPA: Texnologiyanın Təqdimatı

Qrupda dərc edilmişdir
Müasir inkişaf dünyası həyatı asanlaşdırmaq üçün nəzərdə tutulmuş müxtəlif spesifikasiyalarla doludur. Alətləri bilməklə, düzgün birini seçə bilərsiniz. Bilmədən həyatınızı çətinləşdirə bilərsiniz. Bu baxış JPA - Java Persistence API konsepsiyası üzərindəki məxfilik pərdəsini qaldıracaq. Ümid edirəm ki, oxuduqdan sonra bu sirli dünyaya daha da dərinə dalmaq istəyəcəksiniz.
JPA : Texnologiyaya Giriş - 1

Giriş

Bildiyimiz kimi, proqramların əsas vəzifələrindən biri məlumatların saxlanması və işlənməsidir. Köhnə yaxşı günlərdə insanlar məlumatları sadəcə olaraq fayllarda saxlayırdılar. Ancaq eyni vaxtda oxumaq və redaktə etmək imkanı lazım olduqda, yük olduqda (yəni, eyni vaxtda bir neçə sorğu daxil olur), məlumatların sadəcə olaraq fayllarda saxlanması problemə çevrilir. Verilənlər bazalarının hansı problemləri və necə həll etdiyi haqqında daha çox məlumat üçün sizə “ Verilənlər bazası necə qurulur ” məqaləsini oxumağı məsləhət görürəm . Bu o deməkdir ki, biz məlumatlarımızı verilənlər bazasında saxlamağa qərar veririk. Uzun müddətdir ki, Java JDBC API (The Java Database Connectivity) istifadə edərək verilənlər bazası ilə işləyə bilir. JDBC haqqında daha ətraflı burada oxuya bilərsiniz: " JDBC və ya hər şeyin başladığı yer ." Lakin vaxt keçdi və tərtibatçılar hər dəfə Java obyektlərinin verilənlər bazasında saxlanması və əksinə, Java obyektlərinin yaradılması üçün eyni tipli və lazımsız “xidmət” kodunu (Qan kodu adlanan) yazmaq ehtiyacı ilə üzləşdilər. verilənlər bazası. Və sonra, bu problemləri həll etmək üçün ORM kimi bir konsepsiya yarandı. ORM - Obyekt-Relational Xəritəçəkmə və ya rus dilinə tərcümə edilmiş obyekt-relational Xəritəçəkmə. Bu, verilənlər bazalarını obyekt yönümlü proqramlaşdırma dilləri anlayışları ilə əlaqələndirən proqramlaşdırma texnologiyasıdır. Sadələşdirmək üçün ORM Java obyektləri ilə verilənlər bazasındakı qeydlər arasında əlaqədir: JPA: Texnologiyaya Giriş - 2ORM mahiyyətcə Java obyektinin verilənlər bazasında verilənlər kimi təqdim oluna biləcəyi anlayışıdır (və əksinə). O, JPA spesifikasiyası - Java Persistence API şəklində təcəssüm olunub. Spesifikasiya artıq bu konsepsiyanı ifadə edən Java API-nin təsviridir. Spesifikasiya ORM konsepsiyasına uyğun işləmək üçün bizə hansı alətlərlə təmin edilməli olduğumuzu (yəni, hansı interfeyslərlə işləyə biləcəyimizi) bildirir. Və bu vəsaitləri necə istifadə etmək olar. Spesifikasiya alətlərin həyata keçirilməsini təsvir etmir. Bu, bir spesifikasiya üçün müxtəlif tətbiqlərdən istifadə etməyə imkan verir. Siz onu sadələşdirə və spesifikasiyanın API-nin təsviri olduğunu söyləyə bilərsiniz. JPA spesifikasiyasının mətnini Oracle saytında tapa bilərsiniz: " JSR 338: JavaTM Persistence API ". Buna görə də, JPA-dan istifadə etmək üçün texnologiyadan istifadə edəcəyimiz bəzi tətbiqlərə ehtiyacımız var. JPA tətbiqlərinə JPA Provayderləri də deyilir. Ən diqqətəlayiq JPA tətbiqlərindən biri Hibernate- dir . Ona görə də bunu nəzərdən keçirməyi təklif edirəm.
JPA: Texnologiyaya Giriş - 3

Layihənin yaradılması

JPA Java haqqında olduğundan, bizə Java layihəsi lazım olacaq. Kataloq strukturunu özümüz əl ilə yarada və lazımi kitabxanaları özümüz əlavə edə bilərik. Lakin layihələrin yığılmasının avtomatlaşdırılması sistemlərindən istifadə etmək daha rahat və düzgündür (yəni, mahiyyət etibarı ilə bu, sadəcə olaraq bizim üçün layihələrin yığılmasını idarə edəcək proqramdır. Kataloqlar yaradın, sinif yoluna lazımi kitabxanaları əlavə edin və s. .). Belə sistemlərdən biri Gradle sistemidir. Gradle haqqında daha ətraflı burada oxuya bilərsiniz: " Qradle qısa giriş ". Bildiyimiz kimi, Gradle funksionallığı (yəni onun edə biləcəyi işlər) müxtəlif Gradle Pluginlərindən istifadə etməklə həyata keçirilir. Gəlin Gradle və " Gradle Build Init Plugin " plaginindən istifadə edək. Komandanı icra edək:

gradle init --type java-application
Gradle bizim üçün lazımi kataloq strukturunu edəcək və tikinti skriptində layihənin əsas deklarativ təsvirini yaradacaq build.gradle. Beləliklə, bir müraciətimiz var. Tətbiqimizlə nəyi təsvir etmək və ya modelləşdirmək istədiyimizi düşünməliyik. Bəzi modelləşdirmə alətlərindən istifadə edək, məsələn: app.quickdatabasediagrams.com JPA: Texnologiyaya Giriş - 4 Burada təsvir etdiyimiz şeyin bizim “domen modelimiz” olduğunu söyləməyə dəyər. Domen “mövzu sahəsidir”. Ümumiyyətlə, domen latınca “sahiplik” deməkdir. Orta əsrlərdə kralların və ya feodalların sahib olduğu ərazilərə belə ad verilirdi. Və fransız dilində bu, sadəcə olaraq "sahə" kimi tərcümə olunan "domain" sözünə çevrildi. Beləliklə, biz “domen modelimiz” = “mövzu modelimizi” təsvir etdik. Bu modelin hər bir elementi bir növ "mahiyyət", real həyatdan bir şeydir. Bizim vəziyyətimizdə bunlar obyektlərdir: Kateqoriya ( Category), Mövzu ( Topic). Gəlin obyektlər üçün ayrıca bir paket yaradaq, məsələn, ad modeli ilə. Və orada obyektləri təsvir edən Java siniflərini əlavə edək. Java kodunda bu cür obyektlər adi POJO- dur və bu kimi görünə bilər:
public class Category {
    private Long id;
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
Sinfin məzmununu kopyalayaq və analogiya ilə bir sinif yaradaq Topic. O, yalnız mənsub olduğu kateqoriya haqqında bildikləri ilə fərqlənəcək. TopicBuna görə də, sinfə kateqoriya sahəsi və onunla işləmək üsullarını əlavə edək :
private Category category;

public Category getCategory() {
	return category;
}

public void setCategory(Category category) {
	this.category = category;
}
İndi bizim öz domen modeli olan Java proqramımız var. İndi JPA layihəsinə qoşulmağa başlamağın vaxtıdır.
JPA: Texnologiyaya Giriş - 5

JPA əlavə olunur

Beləliklə, xatırladığımız kimi, JPA o deməkdir ki, verilənlər bazasında nəyisə saxlayacağıq. Ona görə də bizə verilənlər bazası lazımdır. Layihəmizdə verilənlər bazası bağlantısından istifadə etmək üçün verilənlər bazasına qoşulmaq üçün asılılıq kitabxanası əlavə etməliyik. Xatırladığımız kimi, bizim üçün tikinti skripti yaradan Gradle istifadə etdik build.gradle. Orada layihəmizin ehtiyac duyduğu asılılıqları təsvir edəcəyik. Asılılıqlar o kitabxanalardır ki, onsuz kodumuz işləyə bilməz. Verilənlər bazasına qoşulmaqdan asılılığın təsviri ilə başlayaq. Biz bunu JDBC ilə işləsək, eyni şəkildə edirik:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
İndi verilənlər bazamız var. İndi tətbiqimizə Java obyektlərimizi verilənlər bazası anlayışlarına (Java-dan SQL-ə) uyğunlaşdırmaq üçün cavabdeh olan təbəqə əlavə edə bilərik. Xatırladığımız kimi, bunun üçün Hibernate adlı JPA spesifikasiyasının tətbiqindən istifadə edəcəyik:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
	implementation 'org.hibernate:hibernate-core:5.4.2.Final'
İndi JPA-nı konfiqurasiya etməliyik. Spesifikasiyanı və "8.1 Davamlılıq Vahidi" bölməsini oxusaq, Davamlılıq Vahidinin konfiqurasiyaların, metadataların və obyektlərin bir növ birləşməsinin olduğunu biləcəyik. JPA-nın işləməsi üçün konfiqurasiya faylında ən azı bir Davamlılıq Vahidini təsvir etməlisiniz persistence.xml. Onun yeri "8.2 Persistence Unit Packaging" spesifikasiya bölməsində təsvir edilmişdir. Bu bölməyə görə, əgər bizim Java SE mühitimiz varsa, o zaman onu META-INF kataloqunun kökünə qoymalıyıq.
JPA: Texnologiyaya Giriş - 6
Gəlin məzmunu " " bölməsindəki JPA spesifikasiyasında verilmiş nümunədən kopyalayaq 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>
Lakin bu kifayət deyil. JPA Provayderimizin kim olduğunu söyləməliyik, yəni. JPA spesifikasiyasını həyata keçirən biri:
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
İndi parametrləri əlavə edək ( properties). Onlardan bəziləri ( ilə başlayan javax.persistence) standart JPA konfiqurasiyalarıdır və "8.2.1.9 xüsusiyyətləri" bölməsindəki JPA spesifikasiyasında təsvir edilmişdir. Bəzi konfiqurasiyalar provayderə xasdır (bizim halda, onlar Jpa Provayderi kimi Hibernate-ə təsir edir. Bizim parametrlər blokumuz belə görünəcək:
<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>
İndi JPA uyğun konfiqurasiyamız var persistence.xml, JPA provayderi Hibernate var və H2 verilənlər bazası var və bizim domen modelimiz olan 2 sinif də var. Gəlin, nəhayət, bütün bunları işə salaq. Kataloqda /test/javaGradle lütfən Vahid testləri üçün şablon yaratdı və onu AppTest adlandırdı. Gəlin istifadə edək. JPA spesifikasiyasının "7.1 Davamlılıq Kontekstləri" fəslində qeyd edildiyi kimi, JPA dünyasındakı qurumlar Davamlılıq Konteksti adlı məkanda yaşayırlar. Lakin biz Persistence Context ilə birbaşa işləmirik. Bunun üçün biz Entity Managervə ya "müəssisə meneceri" istifadə edirik. Kontekst və orada hansı varlıqların yaşadığını bilən odur. Biz Entity Manager'om ilə qarşılıqlı əlaqədəyik. Onda qalan tək şey anlamaqdır ki, bunu haradan əldə edə bilərik Entity Manager? JPA spesifikasiyasının "7.2.2 Tətbiqlə idarə olunan Müəssisə Menecerinin əldə edilməsi" fəslinə uyğun olaraq istifadə etməliyik EntityManagerFactory. Buna görə də, gəlin JPA spesifikasiyası ilə silahlandıraq və “7.3.2 Java SE Mühitində Müəssisə Meneceri Fabriki əldə etmək” fəslindən nümunə götürək və onu sadə Birlik testi şəklində formatlaşdıraq:
@Test
public void shouldStartHibernate() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	EntityManager entityManager = emf.createEntityManager();
}
Bu test artıq "Tanınmayan JPA persistence.xml XSD versiyası" xətasını göstərəcək. Səbəb, persistence.xmlJPA spesifikasiyasında "8.3 persistence.xml Sxema" bölməsində qeyd edildiyi kimi istifadə etmək üçün sxemi düzgün təyin etməlisiniz:
<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 əlavə, elementlərin sırası vacibdir. Buna görə də, providersinifləri sadalamadan əvvəl dəqiqləşdirilməlidir. Bundan sonra test uğurla davam edəcək. Biz birbaşa JPA bağlantısını tamamladıq. Davam etməzdən əvvəl, qalan testlər haqqında düşünək. Testlərimizin hər biri tələb olunacaq EntityManager. Əmin edək ki, EntityManagericranın əvvəlində hər bir testin özünəməxsusluğu var. Bundan əlavə, verilənlər bazasının hər dəfə yeni olmasını istəyirik. Variantdan istifadə etdiyimizə görə inmemorybağlamaq kifayətdir EntityManagerFactory. Yaradılması Factorybahalı əməliyyatdır. Ancaq sınaqlar üçün bu, haqlıdır. JUnit sizə hər bir testin icrasından əvvəl (əvvəl) və sonra (sonra) yerinə yetiriləcək metodları müəyyən etməyə imkan verir:
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();
    }
İndi, hər hansı bir testi yerinə yetirməzdən əvvəl, yenisi yaradılacaq EntityManagerFactory, bu da yeni verilənlər bazasının yaradılmasına səbəb olacaq, çünki hibernate.hbm2ddl.automənası var create. Və yeni fabrikdən yenisini alacağıq EntityManager.
JPA: Texnologiyaya Giriş - 7

Müəssisələr

Xatırladığımız kimi, biz əvvəllər domen modelimizi təsvir edən siniflər yaratmışdıq. Artıq dedik ki, bunlar bizim “mahiyyətlərimizdir”. Bu, istifadə edərək idarə edəcəyimiz Müəssisədir EntityManager. Bir kateqoriyanın mahiyyətini saxlamaq üçün sadə bir test yazaq:
@Test
public void shouldPersistCategory() {
	Category cat = new Category();
	cat.setTitle("new category");
	// JUnit обеспечит тест свежим EntityManager'ом
	em.persist(cat);
}
Amma bu sınaq dərhal nəticə verməyəcək, çünki... obyektlərin nə olduğunu anlamağımıza kömək edəcək müxtəlif səhvlər alacağıq:
  • Unknown entity: hibernate.model.Category
    CategoryNiyə Hibernate bunun nə olduğunu başa düşmür entity? İş ondadır ki, qurumlar JPA standartına uyğun olaraq təsvir edilməlidir. JPA spesifikasiyasının "2.1 Müəssisə Sinfi" fəslində qeyd edildiyi kimi,
    obyekt sinifləri annotasiya ilə qeyd edilməlidir .@Entity

  • No identifier specified for entity: hibernate.model.Category
    Müəssisələrin bir qeydi digərindən fərqləndirmək üçün istifadə edilə bilən unikal identifikatoru olmalıdır.
    JPA spesifikasiyasının "2.4 İlkin Açarlar və Müəssisə İdentifikasiyası" fəslinə əsasən, "Hər bir qurumun əsas açarı olmalıdır", yəni. Hər bir qurumun "əsas açarı" olmalıdır. Belə əsas açar annotasiya ilə müəyyən edilməlidir@Id

  • ids for this class must be manually assigned before calling save()
    Şəxsiyyət vəsiqəsi haradansa gəlməlidir. Əl ilə təyin edilə bilər və ya avtomatik olaraq əldə edilə bilər.
    Buna görə də, "11.2.3.3 Yaradılmış Dəyər" və "11.1.20 Yaradılmış Dəyər Annotasiyası" fəsillərində göstərildiyi kimi annotasiyanı təyin edə bilərik @GeneratedValue.

Beləliklə, kateqoriya sinfinin obyektə çevrilməsi üçün aşağıdakı dəyişiklikləri etməliyik:
@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;
Bundan əlavə, annotasiya @Idhansının istifadə olunacağını göstərir Access Type. Siz giriş növü haqqında daha çox JPA spesifikasiyasının "2.3 Giriş növü" bölməsində oxuya bilərsiniz. Qısaca desək, çünki... @Idsahəsində ( ) yuxarıda qeyd etdik , onda giriş növü deyil, fielddefault olacaq . Buna görə də, JPA provayderi dəyərləri birbaşa sahələrdən oxuyacaq və saxlayacaq. Əgər alıcının üstünə yerləşdirsək , onda giriş istifadə olunacaq, yəni. alıcı və təyinat vasitəsi ilə. Testi işləyərkən verilənlər bazasına hansı sorğuların göndərildiyini də görürük (seçim sayəsində ). Amma qənaət edəndə heç bir 's görmürük . Belə çıxır ki, biz əslində heç nə saxlamamışıq? JPA sizə metoddan istifadə edərək davamlılıq kontekstini və verilənlər bazasını sinxronizasiya etməyə imkan verir : field-basedproperty-based@Idproperty-basedhibernate.show_sqlinsertflush
entityManager.flush();
Amma indi icra etsək, xəta alacağıq: heç bir əməliyyat aparılmır . İndi JPA-nın əməliyyatlardan necə istifadə etdiyini öyrənməyin vaxtı gəldi.
JPA: Texnologiyaya Giriş - 8

JPA əməliyyatları

Xatırladığımız kimi, JPA əzmkarlıq kontekstinin konsepsiyasına əsaslanır. Bu, varlıqların yaşadığı yerdir. Və biz qurumları vasitəsilə idarə edirik EntityManager. Biz əmri yerinə yetirdikdə persistobyekti kontekstdə yerləşdiririk. Daha doğrusu, biz EntityManagersizə deyirik ki, bunu etmək lazımdır. Ancaq bu kontekst yalnız bəzi saxlama sahəsidir. Hətta bəzən onu "birinci səviyyəli keş" də adlandırırlar. Amma onun verilənlər bazasına qoşulması lazımdır. Əvvəllər xəta ilə uğursuz olan əmr flush, davamlılıq kontekstindən məlumatları verilənlər bazası ilə sinxronlaşdırır. Amma bu nəqliyyat tələb edir və bu nəqliyyat əməliyyatdır. JPA-da əməliyyatlar spesifikasiyanın "7.5 Nəzarət Əməliyyatları" bölməsində təsvir edilmişdir. JPA-da əməliyyatlardan istifadə etmək üçün xüsusi API mövcuddur:
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
Testlərdən əvvəl və sonra işləyən kodumuza əməliyyatların idarə edilməsini əlavə etməliyik:
@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();
}
Əlavə etdikdən sonra daxiletmə jurnalında SQL-də əvvəllər olmayan bir ifadəni görəcəyik:
JPA: Texnologiyaya Giriş - 9
Tranzaksiyada toplanmış dəyişikliklər EntityManagerverilənlər bazasında edildi (təsdiqləndi və saxlanıldı). İndi öz mahiyyətimizi tapmağa çalışaq. Gəlin identifikatoru ilə obyekti axtarmaq üçün test yaradaq:
@Test
public void shouldFindCategory() {
	Category cat = new Category();
	cat.setTitle("test");
	em.persist(cat);
	Category result = em.find(Category.class, 1L);
	assertNotNull(result);
}
Bu halda, biz əvvəllər saxladığımız obyekti alacağıq, lakin jurnalda SELECT sorğularını görməyəcəyik. Və hər şey dediyimizə əsaslanır: “Müəssisə Meneceri, zəhmət olmasa mənə ID=1 olan Kateqoriya obyektini tapın.” Və müəssisə meneceri əvvəlcə kontekstinə baxır (bir növ keşdən istifadə edir) və yalnız onu tapmasa, verilənlər bazasına baxmağa gedir. SELECTID-ni 2-yə dəyişdirməyə dəyər (belə bir şey yoxdur, biz yalnız 1 nümunəni saxladıq) və sorğunun göründüyünü görəcəyik . Çünki kontekstdə heç bir obyekt tapılmadı və EntityManagerverilənlər bazası obyekti tapmağa çalışır.Kontekstdə obyektin vəziyyətinə nəzarət etmək üçün istifadə edə biləcəyimiz müxtəlif əmrlər var. Varlığın bir vəziyyətdən digər vəziyyətə keçməsi varlığın həyat dövrü adlanır - lifecycle.
JPA: Texnologiyaya Giriş - 10

Müəssisə Həyat Dövrü

Müəssisələrin həyat dövrü JPA spesifikasiyasında "3.2 Müəssisə Nümunəsinin Həyat Dövrü" fəslində təsvir edilmişdir. Çünki subyektlər bir kontekstdə yaşayır və tərəfindən idarə olunur EntityManager, sonra deyirlər ki, subyektlər idarə olunur, yəni. idarə etdi. Gəlin bir varlığın həyatının mərhələlərinə nəzər salaq:
// 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);
Və onu birləşdirmək üçün bir diaqram var:
JPA: Texnologiyaya Giriş - 11
JPA: Texnologiyaya Giriş - 12

Xəritəçəkmə

JPA-da biz varlıqların bir-birləri arasındakı əlaqələrini təsvir edə bilərik. Xatırlayaq ki, biz domen modelimizlə məşğul olanda artıq varlıqların bir-birimizlə əlaqələrinə baxmışıq. Sonra quickdatabasediagrams.com resursundan istifadə etdik :
JPA: Texnologiyaya Giriş - 13
Müəssisələr arasında əlaqələrin qurulmasına xəritəçəkmə və ya assosiasiya (Association Mappings) deyilir. JPA-dan istifadə etməklə yaradıla bilən assosiasiya növləri aşağıda təqdim olunur:
JPA : Texnologiyaya Giriş - 14
TopicMövzunu təsvir edən varlığa baxaq . Topicmünasibət haqqında nə deyə bilərik Category? Çoxları Topicbir kateqoriyaya aid olacaq. Ona görə də bir dərnəyə ehtiyacımız var ManyToOne. Gəlin bu əlaqəni JPA-da ifadə edək:
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
Hansı annotasiyaların qoyulacağını xatırlamaq üçün sonuncu hissənin yuxarıda annotasiyanın göstərildiyi sahəyə cavabdeh olduğunu xatırlaya bilərsiniz. ToOne- konkret misal. ToMany- kolleksiyalar. İndi əlaqəmiz birtərəflidir. Gəlin bunu ikitərəfli ünsiyyətə çevirək. Gəlin bu kateqoriyaya daxil olan Categoryhər kəs haqqında biliyə əlavə edək . TopicBu ilə bitməlidir ToMany, çünki bizim siyahımız var Topic. Yəni “Bir çox mövzuya” münasibət. Sual qalır - OneToManyvə ya ManyToMany:
JPA: Texnologiyaya Giriş - 15
Eyni mövzuda yaxşı cavabı burada oxuya bilərsiniz: " ORM oneToMany, manyToMany əlaqəsini mən beş yaşında olduğum kimi izah edin ". Kateqoriyanın ToManymövzularla əlaqəsi varsa, bu mövzuların hər birinin yalnız bir kateqoriyası ola bilər, o zaman bu olacaq One, əks halda Many. Beləliklə, Categorybütün mövzuların siyahısı belə görünəcək:
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "topic_id")
private Set<Topic> topics = new HashSet<>();
CategoryBütün mövzuların siyahısını əldə etmək üçün mahiyyətcə alıcı yazmağı unutmayaq :
public Set<Topic> getTopics() {
	return this.topics;
}
İki istiqamətli əlaqələri avtomatik izləmək çox çətin bir şeydir. Buna görə də, JPA bu məsuliyyəti tərtibatçıya keçir. TopicBunun bizim üçün mənası odur ki, ilə qurum əlaqəsi qurarkən Categoryməlumatların ardıcıllığını özümüz təmin etməliyik. Bu, sadəcə olaraq edilir:
public void setCategory(Category category) {
	category.getTopics().add(this);
	this.category = category;
}
Yoxlamaq üçün sadə bir test yazaq:
@Test
public void shouldPersistCategoryAndTopics() {
	Category cat = new Category();
	cat.setTitle("test");
	Topic topic = new Topic();
	topic.setTitle("topic");
	topic.setCategory(cat);
 	em.persist(cat);
}
Xəritəçəkmə tamamilə ayrı bir mövzudur. Bu baxışın məqsədi buna nail olmaq üsullarını başa düşməkdir. Xəritəçəkmə haqqında daha ətraflı burada oxuya bilərsiniz:
JPA : Texnologiyaya Giriş - 16

JPQL

JPA maraqlı bir alət təqdim edir - Java Persistence Query Language-də sorğular. Bu dil SQL-ə bənzəyir, lakin SQL cədvəllərindən çox Java obyekt modelindən istifadə edir. Bir misala baxaq:
@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());
}
Gördüyümüz kimi sorğuda Categorycədvələ deyil, obyektə istinaddan istifadə etdik. Həm də bu qurumun sahəsində title. JPQL bir çox faydalı xüsusiyyətləri təmin edir və öz məqaləsinə layiqdir. Ətraflı təfərrüatları rəydə tapa bilərsiniz:
JPA : Texnologiyaya Giriş - 17

Kriteriyalar API

Və nəhayət, Kriteriya API-yə toxunmaq istərdim. JPA dinamik sorğu qurma alətini təqdim edir. Criteria API-dən istifadə nümunəsi:
@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 nümunə " " sorğusunun icrasına bərabərdir SELECT c FROM Category c. Criteria API güclü vasitədir. Bu barədə daha ətraflı burada oxuya bilərsiniz:

Nəticə

Gördüyümüz kimi, JPA çox sayda xüsusiyyət və alət təqdim edir. Onların hər biri təcrübə və bilik tələb edir. Hətta JPA baxışı çərçivəsində hər şeyi qeyd etmək mümkün deyildi, detallı bir dalışdan bəhs etməmək. Ancaq ümid edirəm ki, oxuduqdan sonra ORM və JPA nədir, onun necə işlədiyi və onunla nə edilə biləcəyi daha aydın oldu. Yaxşı, qəlyanaltı üçün müxtəlif materiallar təklif edirəm: #Viaçeslav
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION