JavaRush /Java блогу /Random-KY /JPA: Технологияны киргизүү
Viacheslav
Деңгээл

JPA: Технологияны киргизүү

Группада жарыяланган
Заманбап өнүгүү дүйнөсү жашоону жеңилдетүү үчүн иштелип чыккан ар кандай мүнөздөмөлөргө толгон. куралдарды билүү, сиз туура бирин тандап алат. Билбей туруп жашооңду кыйындата аласың. Бул кароо JPA - Java Persistence API концепциясынын үстүнөн жашыруундуктун пардасын алып салат. Окуп чыккандан кийин бул сырдуу дүйнөгө дагы тереңирээк сүңгүүнү каалайсыз деп ишенем.
JPA : Технологияга киришүү - 1

Киришүү

Белгилүү болгондой, программалардын негизги милдеттеринин бири маалыматтарды сактоо жана иштетүү болуп саналат. Эски жакшы күндөрдө адамдар жөн гана файлдарда маалыматтарды сакташчу. Бирок, бир эле убакта окуу жана түзөтүү мүмкүнчүлүгү талап кылынары менен, жүк болгондо (б.а., бир эле учурда бир нече сурамдар келип түшкөндө), маалыматтарды жөн эле файлдарда сактоо көйгөйгө айланат. Берorштер базасы кандай көйгөйлөрдү чечет жана кантип жөнүндө көбүрөөк маалымат алуу үчүн, мен сизге макаланы окууну сунуштайм " Маалыматтар базалары кантип түзүлөт ." Бул биздин маалыматтарыбызды маалымат базасында сактоону чечкенибизди билдирет. Көптөн бери Java JDBC API (The Java Database Connectivity) аркылуу маалымат базалары менен иштей алган. JDBC жөнүндө кененирээк бул жерден окуй аласыз: " JDBC же баары кайдан башталат ." Бирок убакыт өтүп, иштеп чыгуучулар ар бир жолу Java an objectилерин маалымат базасында сактоо жана тескерисинче, Java an objectилерин түзүү үчүн бир эле типтеги жана керексиз “тейлөө” codeун (Бойлерплата деп аталган) жазуу зарылдыгына туш болушту. маалымат базасы. Анан бул маселелерди чечүү үчүн ORM сыяктуу түшүнүк пайда болду. ORM - Object-Relational Mapping же орус тorне которулган an object-реляциялык карта. Бул маалымат базаларын an objectиге багытталган программалоо тилдеринин түшүнүктөрү менен байланыштырган программалоо технологиясы. Жөнөкөйлөтүш үчүн, ORM бул Java an objectилери менен маалымат базасындагы жазуулардын ортосундагы байланыш: JPA: Технологияга киришүү - 2ORM негизинен Java an objectисин маалымат базасында маалымат катары көрсөтүүгө болот деген түшүнүк (жана тескерисинче). Ал JPA спецификациясы түрүндө камтылган - Java Persistence API. спецификация мурунтан эле бул түшүнүктү билдирген Java API сыпаттамасы болуп саналат. Спецификация бизге ORM концепциясына ылайык иштөө үчүн кандай куралдар менен камсыз болушубуз керектигин (б.а., биз кандай интерфейстер аркылуу иштей алабыз) айтып берет. Ал эми бул каражаттарды кантип колдонуу керек. спецификация инструменттердин ишке ашырылышын сүрөттөбөйт. Бул бир спецификация үчүн ар кандай ишке ашырууларды колдонууга мүмкүндүк берет. Сиз аны жөнөкөйлөтүп, спецификация API'нин сүрөттөлүшү деп айта аласыз. JPA спецификациясынын текстин Oracle веб-сайтынан тапса болот: " JSR 338: JavaTM Persistence API ". Ошондуктан, JPA колдонуу үчүн, биз технологияны колдоно турган кээ бир ишке ашыруу керек. JPA ишке ашыруулары JPA Провайдерлери деп да аталат. Эң көрүнүктүү JPA ишке ашырууларынын бири - Hibernate . Ошондуктан мен аны карап чыгууну сунуш кылам.
JPA: Технологияга киришүү - 3

Долбоорду түзүү

JPA Java жөнүндө болгондуктан, бизге Java долбоору керек болот. Каталог түзүмүн өзүбүз кол менен түзүп, керектүү китепканаларды өзүбүз кошо алабыз. Бирок долбоорлорду чогултууну автоматташтыруу тутумдарын колдонуу алда канча ыңгайлуу жана туура (б.а., бул жөн гана биз үчүн долбоорлорду чогултууну башкара турган программа. Каталогдорду түзүңүз, класстык жолго керектүү китепканаларды кошуңуз ж.б.у.с.) .). Мындай системалардын бири Gradle болуп саналат. Gradle жөнүндө кененирээк бул жерден окуй аласыз: " Градлга кыскача киришүү ". Белгилүү болгондой, Gradle функционалдуулугу (б.а. ал жасай ала турган нерселер) ар кандай Gradle Plugins аркылуу ишке ашырылат. Келгиле, Gradle жана " Gradle Build Init Plugin " плагинин колдонолу. Келиңиз, буйрукту иштетели:

gradle init --type java-application
Gradle биз үчүн керектүү каталог түзүмүн жасайт жана куруу скриптинде долбоордун негизги декларативдик сүрөттөмөсүн түзөт build.gradle. Демек, бизде арыз бар. Колдонмобуз менен эмнени сүрөттөгүбүз же моделдешибиз керектиги жөнүндө ойлонушубуз керек. Келгиле, кээ бир моделдөө куралын колдонолу, мисалы: app.quickdatabasediagrams.com JPA: Технологияга киришүү - 4 Бул жерде биз сүрөттөгөн нерсе биздин “домен модели” экенин айтууга болот. Домен - бул "предметтик аймак". Жалпысынан алганда, домен латын тorнде "ээлик" болуп саналат. Орто кылымдарда падышалардын же феодалдардын ээлик кылган аймактары ушундай аталыш болгон. Ал эми французча бул жөн эле "аймак" деп которулган "домен" деген сөз болуп калды. Ошентип, биз "домен моделин" = "предметтик моделди" сүрөттөп бердик. Бул моделдин ар бир элементи кандайдыр бир "маңыз", чыныгы жашоодон бир нерсе. Биздин учурда бул an objectтер: Категория ( Category), Тема ( Topic). Келгиле, субъекттер үчүн өзүнчө пакет түзөлү, мисалы, аталыш модели менен. Жана ал жакка an objectтерди сүрөттөгөн Java класстарын кошолу. Java codeунда мындай 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'
Азыр бизде маалымат базасы бар. Эми биз Java an objectилерибизди маалымат базасынын концепцияларына (Javaдан SQLге чейин) картага түшүрүүгө жооптуу болгон тиркемебизге катмар кошо алабыз. Эсибизде тургандай, биз бул үчүн Hibernate деп аталган JPA спецификациясын колдонобуз:

dependencies {
	implementation 'com.h2database:h2:1.4.199'
	implementation 'org.hibernate:hibernate-core:5.4.2.Final'
Эми биз JPA конфигурациялашыбыз керек. Эгерде биз спецификацияны жана "8.1 Persistence Unit" бөлүмүн окусак, туруктуулук бирдиги конфигурациялардын, метаберorштердин жана an objectтердин кандайдыр бир айкалышы экенин билебиз. Жана JPA иштеши үчүн, конфигурация файлында жок дегенде бир Persistence Unit'ти сүрөттөшүңүз керек, ал persistence.xml. Анын жайгашкан жери "8.2 Persistence Unit Packaging" спецификация бөлүмүндө сүрөттөлгөн. Бул бөлүмгө ылайык, бизде 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 конфигурациялары жана "8.2.1.9 касиеттери" бөлүмүндөгү JPA спецификациясында сүрөттөлгөн. Кээ бир конфигурациялар провайдерге мүнөздүү (биздин учурда алар Күтүү режимине 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 боорукердик менен Unit тесттери үчүн шаблонду түзүп, аны AppTest деп атады. Аны колдонолу. JPA спецификациясынын "7.1 Туруктуу контексттери" бөлүмүндө айтылгандай, JPA дүйнөсүндөгү an objectтер Туруктуу контекст деп аталган мейкиндикте жашашат. Бирок биз Persistence Context менен түз иштебейбиз. Бул үчүн биз Entity Manager"an object менеджерин" колдонобуз. Ал контекстти жана ал жерде кандай субъекттер жашап жатканын билет. Биз 'ом менен иштешебиз Entity Manager. Анан муну кайдан алсак болорун түшүнүү гана калды Entity Manager? JPA спецификациясынын "7.2.2 Колдонмо менен башкарылган an object менеджерин алуу" бөлүмүнө ылайык, биз колдонушубуз керек EntityManagerFactory. Ошондуктан, келгиле, JPA спецификациясы менен куралданалы жана "7.3.2 Java SE чөйрөсүндө субъект менеджеринин фабрикасын алуу" бөлүмүнөн мисал алып, аны жөнөкөй Unit тести түрүндө форматтайлы:
@Test
public void shouldStartHibernate() {
	EntityManagerFactory emf = Persistence.createEntityManagerFactory( "JavaRush" );
	EntityManager entityManager = emf.createEntityManager();
}
Бул сыноо мурунтан эле катаны көрсөтөт "Таанылбаган JPA persistence.xml XSD versionсы". Себеби, persistence.xmlJPA спецификациясында "8.3 persistence.xml схемасы" бөлүмүндө айтылгандай, колдонуу үчүн схеманы туура көрсөтүшүңүз керек:
<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ал класстарды тизмектөөдөн мурун тактоо керек. Андан кийин, сыноо ийгorктүү өтөт. Биз түз 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
    CategoryЭмне үчүн Hibernate бул эмне экенин түшүнбөйт entity? Кеп нерсе, субъекттер JPA стандартына ылайык сүрөттөлүшү керек. JPA спецификациясынын "2.1 Объект классы" бөлүмүндө айтылгандай,
    an object класстары annotation менен коштолушу керек .@Entity

  • No identifier specified for entity: hibernate.model.Category
    Объекттерде бир жазууну башкасынан айырмалоо үчүн колдонула турган уникалдуу идентификатор болушу керек.
    JPA спецификациясынын "2.4 Негизги ачкычтар жана субъекттин идентификациясы" бөлүмүнө ылайык, "Ар бир субъекттин негизги ачкычы болушу керек", б.а. Ар бир an objectтин "негизги ачкычы" болушу керек. Мындай негизги ачкыч annotation менен көрсөтүлүшү керек@Id

  • ids for this class must be manually assigned before calling save()
    ID бир жерден келиши керек. Ал кол менен көрсөтүлүшү мүмкүн, же автоматтык түрдө алынышы мүмкүн.
    Ошондуктан, "11.2.3.3 GeneratedValue" жана "11.1.20 GeneratedValue Annotation" бөлүмдөрүндө көрсөтүлгөндөй, биз annotationны белгилей алабыз @GeneratedValue.

Ошентип, категория классы an object болуп калышы үчүн биз төмөнкү өзгөртүүлөрдү киргизишибиз керек:
@Entity
public class Category {
    @Id
    @GeneratedValue
    private Long id;
Мындан тышкары, annotation @Idкайсынысын колдонуу керектигин көрсөтөт Access Type. Сиз JPA спецификациясынын "2.3 Кирүү түрү" бөлүмүнөн кирүү түрү жөнүндө көбүрөөк окуй аласыз. Кыскача айтканда, анткени... биз @Idталаанын жогору жагында ( ), анда кирүү түрү эмес, fieldдемейки болот . Ошондуктан, JPA провайдери маанилерди түздөн-түз талаалардан окуп жана сактайт. Эгерде биз алуучунун үстүнө жайгаштырсак, анда мүмкүндүк колдонулмак, б.а. алуучу жана орнотуучу аркылуу. Сыноону жүргүзүүдө биз маалымат базасына кандай суроо-талаптар жөнөтүлгөнүн көрөбүз (варианттын аркасында ). Бирок үнөмдөөдө биз эч кимди көрбөйбүз . Көрсө, биз эч нерсе сактаган жокпузбу? JPA ыкмасын колдонуу менен туруктуулук контекстти жана маалымат базасын синхрондоштурууга мүмкүндүк берет : field-basedproperty-based@Idproperty-basedhibernate.show_sqlinsertflush
entityManager.flush();
Бирок биз аны азыр аткарсак, ката алабыз: транзакция жүргүзүлбөй жатат . Эми JPA транзакцияларды кантип колдоноору жөнүндө билүүгө убакыт келди.
JPA: Технологияга киришүү - 8

JPA транзакциялары

Эсибизде болгондой, JPA туруктуулук контекстинин концепциясына негизделген. Бул субъекттер жашаган жер. Жана биз аркылуу субъекттерди башкарабыз EntityManager. Биз команданы аткарганда persist, an objectти контекстке киргизебиз. Тагыраак айтканда, EntityManagerмуну жасоо керек деп айтабыз. Бирок бул контекст жөн гана кээ бир сактоо аянты. Ал тургай, кээде "биринчи деңгээл кэш" деп аталат. Бирок аны маалымат базасына туташтыруу керек. Мурда ката менен ишке ашпай калган команда flushтуруктуулук контекстиндеги маалыматтарды маалымат базасы менен синхрондошот. Бирок бул транспортту талап кылат жана бул транспорт бүтүм болуп саналат. JPAдагы операциялар спецификациянын "7.5 Контролдук операциялар" бөлүмүндө сүрөттөлгөн. JPAда транзакцияларды колдонуу үчүн атайын API бар:
entityManager.getTransaction().begin();
entityManager.getTransaction().commit();
Тесттерге чейин жана кийин иштеген codeубузга транзакцияларды башкарууну кошушубуз керек:
@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ти идентификатору боюнча издөө үчүн тест түзөлү:
@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 сурамдарын көрбөйбүз. Жана бардыгы биз айткандарыбызга негизделет: "Ишкананын менеджери, мага ID=1 болгон категориядагы an objectти таап бериңизчи." Ал эми an object менеджери адегенде анын контекстине карайт (кэштин бир түрүн колдонот), эгер ал аны таппаса, маалымат базасына карайт. Идентификаторду 2ге өзгөртүү керек (мындай нерсе жок, биз болгону 1 инстанцияны сактап калдык) жана биз SELECTсурам пайда болгонун көрөбүз. Анткени контекстте эч кандай an object табылган жок жана EntityManagerмаалымат базасы an objectти табууга аракет кылууда.Биз контексттеги an objectтин абалын көзөмөлдөө үчүн колдоно турган ар кандай буйруктар бар. Субъекттин бир абалдан экинчи абалга өтүшү субъекттин жашоо цикли деп аталат - lifecycle.
JPA: Технологияга киришүү - 10

Entity Lifecycle

Объекттердин жашоо цикли JPA спецификациясында "3.2 Объекттин инстанциясынын жашоо цикли" бөлүмүндө сүрөттөлөт. Анткени субъекттер контекстте жашайт жана тарабынан башкарылат 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
Объекттердин ортосундагы байланыштарды түзүү карта же ассоциация (Association Mappings) деп аталат. JPA аркылуу түзүлүшү мүмкүн болгон бирикмелердин түрлөрү төмөндө келтирилген:
JPA : Технологияга киришүү - 14
TopicТеманы сүрөттөгөн an objectти карап көрөлү . Topicмамилеси жөнүндө эмне айтууга болот Category? Көптөр Topicбир категорияга кирет. Ошондуктан, бизге ассоциация керек ManyToOne. Келгиле, бул мамилени JPAда билдирели:
@ManyToOne
@JoinColumn(name = "category_id")
private Category category;
Кайсы annotationларды коюу керектигин эстеп калуу үчүн, акыркы бөлүк жогоруда annotation көрсөтүлгөн талаа үчүн жооптуу экенин эстей аласыз. ToOne- конкреттүү мисал. ToMany- коллекциялар. Азыр биздин байланышыбыз бир тараптуу. Аны эки тараптуу байланышка айландыралы. Келгиле, бул категорияга кирген Categoryар бир адам жөнүндө бorмди кошолу . 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Жана бардык темалардын тизмесин алуу үчүн негизинен Getter жазууну унутпайлы :
public Set<Topic> getTopics() {
	return this.topics;
}
Эки багыттуу мамилелерди автоматтык түрдө көзөмөлдөө өтө кыйын нерсе. Ошондуктан, JPA бул жоопкерчorкти иштеп чыгуучуга өткөрүп берет. 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 Language тorндеги суроону сунуштайт. Бул тил SQLге окшош, бирок SQL tableларына караганда Java an objectисинин моделин колдонот. Келгиле, бир мисал карап көрөлү:
@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());
}
Көрүнүп тургандай, суроодо биз Categorytableга эмес, an objectке шилтеме колдондук. Жана ошондой эле бул жактын талаасында title. JPQL көптөгөн пайдалуу мүмкүнчүлүктөрдү камсыз кылат жана өзүнүн макаласына татыктуу. Көбүрөөк маалыматты кароодон тапса болот:
JPA : Технологияга киришүү - 17

Criteria API

Акыр-аягы, мен Criteria API'ге токтолгум келет. JPA динамикалык суроо куруу куралын киргизет. Criteria API колдонуу мисалы:
@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 көптөгөн функцияларды жана куралдарды камсыз кылат. Алардын ар бири тажрыйбаны жана бorмди талап кылат. JPA карап чыгуунун алкагында да, деталдуу чумкуууну айтпаганда да, бардыгын айтууга мүмкүн болгон жок. Бирок, аны окугандан кийин, ORM жана JPA деген эмне экени, ал кантип иштейт жана аны менен эмне кылса болору түшүнүктүү болду деп үмүттөнөм. Мейли, закуска үчүн мен ар кандай материалдарды сунуштайм: #Вячеслав
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION