JavaRush /Блоги Java /Random-TG /JPA: Муаррифии технология
Viacheslav
Сатҳи

JPA: Муаррифии технология

Дар гурӯҳ нашр шудааст
Ҷаҳони рушди муосир пур аз мушаххасоти мухталифест, ки барои осон кардани ҳаёт пешбинӣ шудаанд. Донистани асбобҳо, шумо метавонед якеро дуруст интихоб кунед. Бехабар шумо метавонед зиндагии худро душвортар созед. Ин барраси пардаи махфиятро бар мафҳуми JPA - Java Persistence API бардошта хоҳад кард. Умедворам, ки пас аз хондан шумо мехоҳед, ки ба ин ҷаҳони пурасрор боз ҳам амиқтар ғарқ шавед.
JPA: Муқаддима ба технология - 1

Муқаддима

Тавре ки маълум аст, яке аз вазифаҳои асосии барномаҳо ҳифз ва коркарди додаҳо мебошад. Дар айёми қадим одамон маълумотро дар файлҳо нигоҳ медоштанд. Аммо вақте ки дастрасии ҳамзамон хондан ва таҳрир кардан лозим аст, вақте ки сарборӣ вуҷуд дорад (яъне, дар як вақт якчанд дархост ворид мешавад), нигоҳ доштани маълумот дар файлҳо мушкил мегардад. Барои гирифтани маълумоти бештар дар бораи кадом мушкилот ва чӣ гуна пойгоҳи додаҳо, ман ба шумо маслиҳат медиҳам, ки мақолаи " Чӣ гуна сохтори пойгоҳи додаҳо " -ро хонед. Ин маънои онро дорад, ки мо тасмим гирифтем, ки маълумоти худро дар пойгоҳи додаҳо нигоҳ дорем. Дар муддати тӯлонӣ, Java тавонист бо истифода аз JDBC API (The Java Database Connectivity) бо пойгоҳи додаҳо кор кунад. Шумо метавонед дар бораи JDBC бештар дар ин ҷо хонед: " JDBC ё аз куҷо ҳамааш оғоз мешавад ." Аммо вақт мегузашт ва таҳиягарон ҳар дафъа ба зарурати навиштани рамзи як навъ ва нолозими "нигоҳдорӣ" (ба истилоҳ codeи Boilerplate) барои амалиётҳои ночизи захира кардани an objectҳои Java дар пойгоҳи додаҳо ва баръакс, сохтани an objectҳои Java бо истифода аз маълумот аз базаи маълумот. Ва он гоҳ, барои ҳалли ин мушкилот, чунин консепсия ба монанди ORM таваллуд шуд. ORM - Харитасозии an object-релятсионӣ ё ба забони русӣ тарҷума шудааст. Ин технологияи барномасозӣ мебошад, ки пойгоҳи додаҳоро бо мафҳумҳои забонҳои барномасозии ба an object нигаронидашуда мепайвандад. Барои содда кардан, ORM пайвасти байни an objectҳои Java ва сабтҳо дар пойгоҳи додаҳо мебошад: JPA: Муқаддима ба технология - 2ORM аслан консепсияест, ки an objectи Java метавонад ҳамчун маълумот дар пойгоҳи додаҳо муаррифӣ шавад (ва баръакс). Он дар шакли мушаххасоти JPA - Java Persistence API таҷассум шудааст. Мушаххасот аллакай тавсифи API-и Java мебошад, ки ин консепсияро ифода мекунад. Мушаххасот ба мо мегӯяд, ки мо бояд бо кадом асбобҳо таъмин карда шавем (яъне, мо бо кадом интерфейсҳо кор карда метавонем) барои кор кардан мувофиқи консепсияи ORM. Ва чй тавр истифода бурдани ин маблагхо. Мушаххасот татбиқи асбобҳоро тавсиф намекунад. Ин имкон медиҳад, ки татбиқи гуногун барои як мушаххасот истифода шавад. Шумо метавонед онро содда кунед ва бигӯед, ки мушаххасот тавсифи API аст. Матни мушаххасоти JPA-ро дар вебсайти Oracle пайдо кардан мумкин аст: " JSR 338: JavaTM Persistence API ". Аз ин рӯ, барои истифодаи JPA, ба мо баъзе татбиқе лозим аст, ки бо он технологияро истифода хоҳем бурд. Амалисозии JPA инчунин провайдерҳои JPA номида мешавад. Яке аз татбиқи назарраси JPA ин Hibernate мебошад . Бинобар ин ман таклиф мекунам, ки онро дида бароем.
JPA: Муқаддима ба технология - 3

Эҷоди лоиҳа

Азбаски JPA дар бораи Java аст, мо ба лоиҳаи Java ниёз дорем. Мо метавонем худамон сохтори директорияро дастӣ созем ва худамон китобхонаҳои заруриро илова кунем. Аммо истифодаи системаҳои автоматикунонии васлкунии лоиҳаҳо хеле қулайтар ва дурусттар аст (яъне, аслан, ин танҳо як барномаест, ки барои мо ҷамъи лоиҳаҳоро идора мекунад. Директорияҳо эҷод кунед, китобхонаҳои заруриро ба синфхона илова кунед ва ғайра. .). Яке аз чунин системаҳо Gradle мебошад. Шумо метавонед бештар дар бораи Gradle дар ин ҷо бихонед: " Муқаддимаи мухтасар ба Gradle ". Тавре ки мо медонем, функсияи Gradle (яъне корҳое, ки он метавонад иҷро кунад) бо истифода аз плагинҳои гуногуни Gradle амалӣ карда мешавад. Биёед Gradle ва плагини " Gradle Build Init Plugin "-ро истифода барем. Биёед фармонро иҷро кунем:

gradle init --type java-application
Gradle барои мо сохтори феҳристи заруриро иҷро мекунад ва тавсифи асосии декларативии лоиҳаро дар скрипти сохтмон эҷод мекунад build.gradle. Инак, мо ариза дорем. Мо бояд дар бораи он фикр кунем, ки мо бо аризаи худ чиро тасвир кардан ё модел кардан мехоҳем. Биёед як асбоби моделсозиро истифода барем, масалан: app.quickdatabasediagrams.com JPA: Муқаддима ба технология - 4 Дар ин ҷо бояд гуфт, ки он чизе, ки мо тавсиф кардем, “модели домейн”-и мост. Домен "минтақаи мавзӯъ" аст. Умуман, домен дар лотинӣ “соҳибӣ” аст. Дар асрҳои миёна минтақаҳоеро, ки ба подшоҳон ё феодалҳо тааллуқ доштанд, ҳамин тавр ном мебурданд. Ва дар фаронсавӣ он калимаи "домен" шуд, ки танҳо ҳамчун "минтақа" тарҷума мешавад. Ҳамин тариқ, мо "модели домейн" = "модели мавзӯъ" -и худро тавсиф кардем. Ҳар як унсури ин модел як навъ "моҳият", чизе аз ҳаёти воқеӣ аст. Дар ҳолати мо, инҳо an objectҳо мебошанд: Категория ( Category), Мавзӯъ ( Topic). Биёед барои an objectҳо бастаи алоҳида эҷод кунем, масалан бо модели ном. Ва биёед дар он ҷо синфҳои Java илова кунем, ки an objectҳоро тавсиф мекунанд. Дар codeи Java, чунин an objectҳо як POJO муқаррарӣ мебошанд , ки метавонанд чунин бошанд:
public class Category {
    private Long id;
    private String title;

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
Биёед мундариҷаи синфро нусхабардорӣ кунем ва аз рӯи аналогия синф эҷод кунем Topic. Ӯ танҳо дар он чизе ки медонад, дар бораи тоифае, ки ба он тааллуқ дорад, фарқ мекунад. Аз ин рӯ, биёед Topicмайдони категория ва усулҳои кор бо он ба синф илова кунем:
private Category category;

public Category getCategory() {
	return category;
}

public void setCategory(Category category) {
	this.category = category;
}
Ҳоло мо як барномаи Java дорем, ки модели домении худро дорад. Ҳоло вақти оғоз кардани пайвастшавӣ ба лоиҳаи JPA расидааст.
JPA: Муқаддима ба технология - 5

Илова кардани JPA

Ҳамин тавр, тавре ки мо дар хотир дорем, JPA маънои онро дорад, ки мо чизеро дар пойгоҳи додаҳо захира мекунем. Аз ин рӯ, мо ба базаи маълумот ниёз дорем. Барои истифодаи пайвасти пойгоҳи додаҳо дар лоиҳаи мо, мо бояд як китобхонаи вобастагӣ барои пайвастшавӣ ба пойгоҳи додаҳо илова кунем. Тавре ки мо дар хотир дорем, мо Gradle-ро истифода мебурдем, ки барои мо скрипти сохтмонӣ эҷод кардааст build.gradle. Дар он мо вобастагиҳоеро тавсиф хоҳем кард, ки ба лоиҳаи мо ниёз доранд. Вобастагӣ он китобхонаҳое мебошанд, ки бе онҳо codeи мо кор карда наметавонад. Биёед бо тавсифи вобастагӣ аз пайвастшавӣ ба пойгоҳи додаҳо оғоз кунем. Мо инро ҳамон тавре иҷро мекунем, ки агар мо танҳо бо JDBC кор мекардем:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
Ҳоло мо базаи маълумот дорем. Ҳоло мо метавонем ба замимаи мо қабате илова кунем, ки барои харитасозии an objectҳои Java-и мо ба консепсияҳои пойгоҳи додаҳо (аз Java то SQL) масъул аст. Тавре ки мо дар хотир дорем, мо барои ин татбиқи мушаххасоти JPA-ро бо номи Hibernate истифода мебарем:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
	implementation 'org.hibernate:hibernate-core:5.4.2.Final'
Ҳоло мо бояд JPA-ро танзим кунем. Агар мо мушаххасот ва қисмати "8.1 Воҳиди устуворӣ" -ро хонем, мо хоҳем донист, ки воҳиди доимӣ як навъ омезиши конфигуратсияҳо, метамаълумотҳо ва an objectҳост. Ва барои кор кардани JPA, шумо бояд ҳадди аққал як воҳиди устуворро дар файли конфигуратсия тавсиф кунед, ки он persistence.xml. Ҷойгиршавии он дар боби мушаххасоти "8.2 бастабандии воҳиди доимӣ" тавсиф шудааст. Мувофиқи ин бахш, агар мо муҳити Java SE дошта бошем, мо бояд онро дар решаи директорияи META-INF гузорем.
JPA: Муқаддима ба технология - 6
Биёед мундариҷаро аз мисоли дар мушаххасоти JPA дар 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>
Аммо ин кифоя нест. Мо бояд бигӯем, ки провайдери JPA-и мо кист, яъне. касе, ки мушаххасоти JPA-ро амалӣ мекунад:
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
Акнун биёед танзимотро илова кунем ( properties). Баъзе аз онҳо (сар карда аз javax.persistence) конфигуратсияҳои стандартии JPA мебошанд ва дар мушаххасоти JPA дар фасли "Хусусиятҳои 8.2.1.9" тавсиф шудаанд. Баъзе конфигуратсияҳо ба провайдер хосанд (дар ҳолати мо, онҳо ба Hibernate ҳамчун провайдери Jpa таъсир мерасонанд. Блоки танзимоти мо чунин хоҳад буд:
<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>
Ҳоло мо конфигуратсияи JPA-и мувофиқ дорем persistence.xml, провайдери JPA Hibernate мавҷуд аст ва пойгоҳи додаи H2 мавҷуд аст ва инчунин 2 синф мавҷуданд, ки модели домени мо мебошанд. Биёед, ниҳоят ин ҳама корро анҷом диҳем. Дар каталог /test/java, Gradle мо бо меҳрубонӣ як қолаби санҷишҳои воҳидиро тавлид кард ва онро AppTest номид. Биёед онро истифода барем. Тавре ки дар боби "7.1 Contexts Persistence" мушаххасоти JPA гуфта шудааст, an objectҳо дар ҷаҳони JPA дар фазое зиндагӣ мекунанд, ки Контексти доимӣ номида мешавад. Аммо мо мустақиман бо Context Persistence кор намекунем. Барои ин мо Entity Managerё "менеҷери an object" -ро истифода мебарем. Маҳз ӯ медонад, ки дар бораи контекст ва дар он ҷо кадом субъектҳо зиндагӣ мекунанд. Мо бо Entity Managerом муомила мекунем. Пас танҳо фаҳмидани он аст, ки мо инро аз куҷо гирифта метавонем Entity Manager? Мувофиқи боби "7.2.2 Гирифтани менеҷери субъекти аз ҷониби барнома идорашаванда" мушаххасоти JPA, мо бояд EntityManagerFactory. Аз ин рӯ, биёед худро бо мушаххасоти JPA муҷаҳҳаз кунем ва аз боби "7.3.2 Гирифтани корхонаи менеҷери субъект дар муҳити Java SE" мисол гирем ва онро дар шакли санҷиши оддии воҳид формат кунем:
@Test
public void shouldStartHibernate() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	EntityManager entityManager = emf.createEntityManager();
}
Ин санҷиш аллакай хатои "Нусхаи JPA persistence.xml XSD номаълум" -ро нишон медиҳад. Сабаб дар он аст, ки persistence.xmlшумо бояд схемаи истифодашударо дуруст муайян кунед, тавре ки дар мушаххасоти JPA дар фасли "8.3 persistence.xml Schema" гуфта шудааст:
<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">
Илова бар ин, тартиби элементҳо муҳим аст. Аз ин рӯ, providerпеш аз номбар кардани синфҳо он бояд муайян карда шавад. Пас аз ин, санҷиш бомуваффақият мегузарад. Мо пайвасти мустақими JPA-ро анҷом додем. Пеш аз он ки ба пеш равем, биёед дар бораи санҷишҳои боқимонда фикр кунем. Ҳар як санҷиши мо талаб мекунад EntityManager. Биёед боварӣ ҳосил кунем, ки ҳар як санҷиш EntityManagerдар оғози иҷроиш худ дорад. Илова бар ин, мо мехоҳем, ки базаи маълумот ҳар дафъа нав бошад. Аз сабаби он, ки мо inmemoryопсияро истифода мебарем, пӯшидани он кофӣ аст EntityManagerFactory. Эҷодкорӣ Factoryяк амалиёти гаронарзиш аст. Аммо барои санҷишҳо он асоснок аст. JUnit ба шумо имкон медиҳад, ки усулҳоеро муайян кунед, ки пеш аз (Пеш) ва баъд аз (Баъд аз) иҷрои ҳар як санҷиш иҷро карда мешаванд:
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();
    }
Ҳоло, пеш аз иҷрои ягон санҷиш, як озмоиши нав эҷод карда мешавад EntityManagerFactory, ки эҷоди пойгоҳи навро дар бар мегирад, зеро hibernate.hbm2ddl.autoмаъно дорад create. Ва аз заводи нав мо заводи нав мегирем EntityManager.
JPA: Муқаддима ба технология - 7

Субъектҳо

Тавре ки мо дар хотир дорем, мо қаблан синфҳоеро эҷод кардем, ки модели домени моро тавсиф мекунанд. Мо аллакай гуфта будем, ки инҳо «моҳиятҳои» мо мебошанд. Ин Муассисаест, ки мо бо истифода аз он идора хоҳем кард EntityManager. Биёед барои нигоҳ доштани моҳияти категория як санҷиши оддӣ нависед:
@Test
public void shouldPersistCategory() {
	Category cat = new Category();
	cat.setTitle("new category");
	// JUnit обеспечит тест свежим EntityManager'ом
	em.persist(cat);
}
Аммо ин санҷиш дарҳол кор нахоҳад кард, зеро... мо хатогиҳои гуногун мегирем, ки ба мо дар фаҳмидани он ки an objectҳо кӯмак мекунанд:
  • Unknown entity: hibernate.model.Category
    Чаро Hibernate намефаҳмад, ки Categoryин чист entity? Гап дар он аст, ки субъектҳо бояд тибқи стандарти JPA тавсиф карда шаванд.
    Синфҳои an objectҳо бояд бо эзоҳ шарҳ дода шаванд @Entity, тавре ки дар боби "2.1 Синфи an objectи" мушаххасоти JPA гуфта шудааст.

  • No identifier specified for entity: hibernate.model.Category
    Субъектҳо бояд идентификатори беназир дошта бошанд, ки онро барои фарқ кардани як сабт аз дигараш истифода бурдан мумкин аст.
    Тибқи боби "2.4 Калидҳои ибтидоӣ ва шахсияти субъект" мушаххасоти JPA, "Ҳар як an object бояд калиди ибтидоӣ дошта бошад", яъне. Ҳар як an object бояд "калиди ибтидоӣ" дошта бошад. Чунин калиди ибтидоӣ бояд тавассути эзоҳ муайян карда шавад@Id

  • ids for this class must be manually assigned before calling save()
    ID бояд аз ҷое биёяд. Он метавонад дастӣ муайян карда шавад, ё он метавонад ба таври худкор ба даст оварда шавад.
    Аз ин рӯ, тавре ки дар бобҳои "11.2.3.3 тавлидшуда" ва "11.1.20 Тавсифи арзиши тавлидшуда" нишон дода шудааст, мо метавонем эзоҳро мушаххас кунем @GeneratedValue.

Ҳамин тавр, барои ба an object табдил додани синфи категория мо бояд тағироти зеринро ворид кунем:
@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;
Илова бар ин, эзоҳ @Idнишон медиҳад, ки кадоме аз онҳо истифода мешавад Access Type. Шумо метавонед маълумоти бештарро дар бораи намуди дастрасӣ дар мушаххасоти JPA, дар бахши "2.3 Навъи дастрасӣ" хонед. Агар хеле мухтасар гуем, зеро... мо @Idдар болои майдон нишон додем ( field), он гоҳ намуди дастрасӣ пешфарз хоҳад буд field-based, на property-based. Аз ин рӯ, провайдери JPA арзишҳоро мустақиман аз майдонҳо мехонад ва нигоҳ медорад. Агар мо @Idдар болои гетер ҷойгир кунем, пас property-basedдастрасӣ истифода мешавад, яъне. тавассути қабулкунанда ва танзимкунанда. Ҳангоми гузаронидани санҷиш, мо инчунин мебинем, ки кадом дархостҳо ба пойгоҳи додаҳо фиристода мешаванд (ба шарофати вариант hibernate.show_sql). Аммо ҳангоми сарфа кардан мо ягон ''ро намебинем insert. Маълум мешавад, ки мо воқеан чизеро захира накардаем? JPA ба шумо имкон медиҳад, ки контексти устуворӣ ва пойгоҳи додаҳоро бо истифода аз усули ҳамоҳанг созед flush:
entityManager.flush();
Аммо агар мо онро ҳозир иҷро кунем, мо хато мегирем: ягон транзаксия ҷараён надорад . Ва ҳоло вақти он расидааст, ки дар бораи он, ки JPA транзаксияҳоро чӣ гуна истифода мебарад.
JPA: Муқаддима ба технология - 8

Муомилоти JPA

Тавре ки мо дар хотир дорем, JPA ба консепсияи контексти устуворӣ асос ёфтааст. Ин маконест, ки an objectҳо зиндагӣ мекунанд. Ва мо an objectҳоро тавассути EntityManager. Вақте ки мо фармонро иҷро мекунем persist, мо an objectро дар контекст ҷойгир мекунем. Аниктараш, мо EntityManagerба шумо мегуем, ки ин корро кардан лозим аст. Аммо ин контекст танҳо як майдони нигоҳдорӣ аст. Он ҳатто баъзан "кэши сатҳи аввал" номида мешавад. Аммо он бояд ба базаи маълумот пайваст карда шавад. Фармони flush, ки қаблан бо хатогӣ ноком шуда буд, маълумотро аз контексти устуворӣ бо пойгоҳи додаҳо ҳамоҳанг мекунад. Аммо ин наќлиётро талаб мекунад ва ин наќлиёт муомилот аст. Муомилот дар JPA дар бахши "7.5 Амалиётҳои назоратӣ" тавсиф карда шудаанд. Барои истифодаи транзаксияҳо дар JPA API махсус вуҷуд дорад:
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
Мо бояд ба рамзи худ идоракунии транзаксияро илова кунем, ки пеш аз санҷиш ва пас аз санҷиш кор мекунад:
@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();
}
Пас аз илова, мо дар сабти дохилкунӣ ифодаеро дар SQL мебинем, ки қаблан вуҷуд надошт:
JPA: Муқаддима ба технология - 9
Тағироти дар EntityManagerтранзаксия ҷамъшуда дар базаи маълумот ворид карда шуданд (тасдиқ ва захира карда шуданд). Биёед ҳоло кӯшиш кунем, ки моҳияти худро пайдо кунем. Биёед барои ҷустуҷӯи an object аз рӯи ID-и он санҷиш эҷод кунем:
@Test
public void shouldFindCategory() {
	Category cat = new Category();
	cat.setTitle("test");
	em.persist(cat);
	Category result = em.find(Category.class, 1L);
	assertNotNull(result);
}
Дар ин ҳолат, мо an objectеро, ки қаблан захира карда будем, мегирем, аммо мо дар гузориш дархостҳои SELECT-ро намебинем. Ва ҳама чиз ба он чизе, ки мо мегӯем, асос ёфтааст: "Менеҷери субъект, лутфан ба ман an objectи Категорияро бо ID=1 пайдо кунед." Ва менеҷери an object аввал ба контексти худ назар мекунад (як навъ кэшро истифода мебарад) ва танҳо агар онро наёбад, вай ба пойгоҳи додаҳо меравад. Лозим аст, ки ID-ро ба 2 тағир диҳед (ин тавр нест, мо танҳо 1 мисолро захира кардем) ва мо мебинем, ки SELECTдархост пайдо мешавад. Зеро дар контекст ягон an object ёфт нашуд ва EntityManagerпойгоҳи додаҳо кӯшиши пайдо кардани an objectро доранд.. Фармонҳои гуногун мавҷуданд, ки мо метавонем онҳоро барои назорат кардани ҳолати an object дар контекст истифода барем. Аз як холат ба холати дигар гузаштани субъектро давраи хаётии субъект - меноманд lifecycle.
JPA: Муқаддима ба технология - 10

Давраи ҳаёт

Давраи зиндагии an objectҳо дар мушаххасоти JPA дар боби "3.2 Давраи зиндагии инстансияи an object" тавсиф шудааст. Зеро субъектҳо дар як контекст зиндагӣ мекунанд ва аз ҷониби - идора карда мешаванд EntityManager, пас онҳо мегӯянд, ки субъектҳо назорат карда мешаванд, яъне. идора карда шуд. Биёед ба марҳилаҳои ҳаёти субъект назар андозем:
// 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);
Ва ин аст диаграмма барои муттаҳид кардани он:
JPA: Муқаддима ба технология - 11
JPA: Муқаддима ба технология - 12

Харитасозӣ

Дар JPA мо метавонем муносибатҳои субъектҳоро байни ҳамдигар тавсиф кунем. Биёед дар хотир дорем, ки мо аллакай ҳангоми баррасии модели домени худ муносибатҳои субъектҳои байни ҳамдигарро дида баромадем. Сипас мо манбаи quickdatabasediagrams.com -ро истифода мебарем :
JPA: Муқаддима ба технология - 13
Барқарор кардани робитаҳо байни an objectҳо харитасозӣ ё ассотсиатсия номида мешавад (Association Mappings). Намудҳои ассотсиатсияҳое, ки метавонанд бо истифода аз JPA таъсис дода шаванд, дар зер оварда шудаанд:
JPA: Муқаддима ба технология - 14
Биёед an objectеро бубинем Topic, ки мавзӯъро тавсиф мекунад. Дар бораи муносибат Topicба Category. Бисёриҳо Topicба як категория тааллуқ хоҳанд дошт. Аз ин рӯ, ба мо иттиҳодия лозим аст ManyToOne. Биёед ин муносибатро дар JPA баён кунем:
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
Барои дар хотир доштан, ки кадом эзоҳҳоро гузоштан мумкин аст, шумо метавонед дар хотир доред, ки қисми охирин барои майдоне, ки дар боло эзоҳ нишон дода шудааст, масъул аст. ToOne- мисоли мушаххас. ToMany- коллексияҳо. Холо алокаи мо яктарафа аст. Биёед онро ба алокаи дутарафа табдил дихем. Биёед ба Categoryдониш дар бораи ҳар касе Topic, ки ба ин гурӯҳ дохил карда шудааст, илова кунем. Он бояд бо тамом шавад ToMany, зеро мо рӯйхат дорем Topic. Яъне муносибати «Ба бисьёр» мавзуъхо. Савол боқӣ мемонад - OneToManyё ManyToMany:
JPA: Муқаддима ба технология - 15
Ҷавоби хубро дар ҳамон мавзӯъ метавон дар инҷо хонд: " Муносибати ORM oneToMany, manyToManyро фаҳмонед, мисли ман панҷсолаам ". Агар категория бо ToManyмавзӯъҳо робита дошта бошад, пас ҳар яке аз ин мавзӯъҳо метавонад танҳо як категория дошта бошад, Oneдар акси ҳол Many. Пас, Categoryрӯйхати ҳамаи мавзӯъҳо чунин хоҳад буд:
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "topic_id")
private Set<Topic> topics = new HashSet<>();
Ва биёед фаромӯш накунем, ки аслан Categoryяк гетер нависед, то рӯйхати ҳама мавзӯъҳоро гиред:
public Set<Topic> getTopics() {
	return this.topics;
}
Муносибатҳои дуҷониба як чизи хеле душвор барои пайгирии худкор мебошанд. Аз ин рӯ, JPA ин масъулиятро ба дӯши таҳиякунанда мегузорад. Ин барои мо чӣ маъно дорад, ки вақте ки мо Topicбо Category. Ин ба таври оддӣ анҷом дода мешавад:
public void setCategory(Category category) {
	category.getTopics().add(this);
	this.category = category;
}
Биёед як санҷиши оддӣ нависед, то тафтиш кунед:
@Test
public void shouldPersistCategoryAndTopics() {
	Category cat = new Category();
	cat.setTitle("test");
	Topic topic = new Topic();
	topic.setTitle("topic");
	topic.setCategory(cat);
 	em.persist(cat);
}
Харитасозӣ як мавзӯи алоҳида аст. Мақсади ин барраси фаҳмидани воситаҳои ба даст овардани ин аст. Шумо метавонед бештар дар бораи харитасозӣ дар ин ҷо хонед:
JPA: Муқаддима ба технология - 16

JPQL

JPA як абзори ҷолибро муаррифӣ мекунад - дархостҳо дар забони Java Persistence Query. Ин забон ба SQL монанд аст, аммо на ҷадвалҳои SQL модели an objectи Java-ро истифода мебарад. Биёед як мисолро дида бароем:
@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());
}
Тавре ки мо мебинем, дар дархост мо истинодро ба an object истифода кардем Category, на ҷадвал. Ва инчунин дар майдони ин ниҳод title. JPQL бисёр хусусиятҳои муфидро пешкаш мекунад ва сазовори мақолаи худ мебошад. Тафсилоти бештарро дар барраси дидан мумкин аст:
JPA: Муқаддима ба технология - 17

Criteria API

Ва дар ниҳоят, ман мехоҳам ба Criteria API дахл кунам. JPA асбоби сохтани пурсишҳои динамикиро ҷорӣ мекунад. Намунаи истифодаи API Criteria:
@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());
}
Ин мисол ба иҷрои дархости " SELECT c FROM Category c" баробар аст. Criteria API як воситаи пурқувват аст. Шумо метавонед дар ин ҷо бештар дар бораи он бихонед:

Хулоса

Тавре ки мо мебинем, JPA шумораи зиёди хусусиятҳо ва асбобҳоро пешниҳод мекунад. Хар кадоми онхо тачриба ва донишро талаб мекунад. Ҳатто дар доираи баррасии JPA, имкон надошт, ки ҳама чизро зикр кунем, ғаввоси муфассалро зикр накунем. Аммо ман умедворам, ки пас аз хондани он маълум шуд, ки ORM ва JPA чист, он чӣ гуна кор мекунад ва бо он чӣ кор кардан мумкин аст. Хуб, барои хӯрокхӯрӣ ман маводи гуногунро пешниҳод мекунам: #Вячеслав
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION