JPA ja Hibernate tarjoavat erilaisia menetelmiä uusien säilymiseen ja olemassa olevien yksiköiden päivittämiseen. Voit valita JPA: n jatkuvat ja yhdistää ja Hibernate: n tallentaa ja päivittää menetelmiä.
näyttää siltä, että on olemassa 2 paria 2 menetelmää, jotka tekevät saman. Voit käyttää menetelmiä säily ja Tallenna tallentaaksesi uuden entiteetin ja menetelmiä yhdistyä ja päivittää tallentaaksesi erillisen entiteetin muutokset tietokantaan. Siksi monet kehittäjät ihmettelevät, mitä näistä menetelmistä heidän pitäisi käyttää. Katsotaanpa tarkemmin yksityiskohtia ja pieniä eroja näiden menetelmien.
erityiskiitokset Steve Ebersolelle (Lead Developer – Hibernate ORM), joka antoi palautetta ja hienoja oivalluksia joistakin Hibernaten piilotetuista toteutustiedoista!
- Entiteettitilojen siirtymät
- uuden entiteetin jatkaminen käyttäen säily tai tallenna
- spesifikaatio vs. Proprietary API
- Paluutyypit ja SQL-lauseiden toteutus
- ei luotu
- luotu IDENTITEETTISTRATEGIALLA
- luotu SEKVENSSISTRATEGIALLA
- luotu TAULUKKOSTRATEGIALLA
- kumpi valitaan?
- Erillisyksikön päivittäminen
- yhteisen parlamentaarisen edustajakokouksen yhdistämismenetelmä
- Hibernaten päivitysmenetelmä
- kumpi valitaan?
- hallitun yksikön päivittäminen
Entiteettitilojen siirtymät
ennen kuin pääsemme näiden 4 menetelmän yksityiskohtiin, minun on annettava teille nopea esittely yhteisen parlamentaarisen edustajakokouksen entiteetin elinkaaritiloista.
jos yhteisö on liitetty nykyiseen pysyvyyskontekstiin, sen elinkaaritilanne on hallittu. Se tarkoittaa, että se on yhdistetty tietokantatallenteeseen. Pysyvyyden tarjoajasi luo tarvittavat SQL-insertti-ja PÄIVITYSLAUSUNNOT kaikkien muutosten levittämiseksi. Hallittu kokonaisuus tallennetaan myös 1. tason välimuistiin.
kun luot uuden entiteetin, se on ohimenevässä tilassa. Se pysyy tässä tilassa, kunnes liität sen nykyiseen pysyvyyskontekstiin. Näytän teille, miten voit tehdä sen JPA: n itsepintainen ja Hibernate n tallenna menetelmä, seuraavassa jaksossa. Niin kauan kuin yhteisö on ohimenevässä tilassa, sitä ei yhdistetä tietokantatietueeseen eikä hallinnoida missään pysyvyyskontekstissa.
irrallaan elinkaaritilassa olevia kokonaisuuksia ei enää hoideta pysyvyyskontekstissa. Näin voi olla, koska suljit pysyvyyskontekstin tai irroitit eksplisiittisesti olion nykyisestä kontekstista. Saan lisätietoja siitä, miten voit kiinnittää nämä yhteisöt uudelleen yhteisen edustajakokouksen merge ja Hibernate päivitysmenetelmät myöhemmin osa tätä viestiä.
ja viimeinen elinkaaritila poistetaan. Nämä entiteetit olivat aiemmin valtion hallinnassa, ennen kuin ajoitit ne poistettaviksi. Kokonaisuuksien poistaminen ei kuulu tämän viran piiriin, joten en mene siitä liian moneen yksityiskohtaan. Voit ajoittaa olion poistettavaksi kutsumalla poista-menetelmää EntityManager-käyttöliittymässä.
uuden entiteetin jatkaminen käyttäen säily tai tallenna
kun luot uuden entiteettiobjektin, se on ohimenevässä elinkaaritilassa. Se ei kartoita mitään tietokantatietuetta.
Author a = new Author();a.setFirstName("Thorben");a.setLastName("Janssen");
Olio on liitettävä pysyvyyskontekstiin, jotta sitä hallitaan ja se pysyy tietokannassa. Voit tehdä sen joko käyttämällä JPA: n itsepintaista tai Hibernaten tallennusmenetelmää. Molemmat menetelmät näyttävät tekevän saman, mutta muutamia eroja on.
spesifikaatio vs. Proprietary API
selvin ero on siinä, että JPA-spesifikaatio määrittelee säilymismenetelmän. Voit käyttää sitä kaikkien JPA toteutukset. Save-menetelmä sen sijaan on Horrostyyppinen. Se ei siis ole käytettävissä muissa yhteisen parlamentaarisen edustajakokouksen toteutuksissa.
, mutta sillä on merkitystä vain, jos haluat korvata Hibernaten toisella YPA-toteutuksella, kuten Eclipse linkillä tai OpenJPA: lla.
Paluutyypit ja SQL-lauseiden toteutus
toinen ilmeinen ero näiden 2 menetelmän välillä on niiden paluutyyppi. JPA: n itsepintainen menetelmä palauttaa mitättömäksi ja Hibernaten save-menetelmä palauttaa olennon ensisijaisen avaimen.
se saattaa tuntua valtavalta erolta, varsinkin kun katsoo tarkemmin Hibernaten javadocia ja parlamentaarisen edustajakokouksen määrittelyä:
- Hibernaten tallennusmenetelmän Javadoc toteaa, että se luo ensisijaisen avaimen arvon ensin:
Jatka annettua ohimenevää instanssia ja anna ensin luotu tunniste.
Javadoc Session.save(yhteisö) - et löydä mitään tietoa tästä yhteisen edustajakokouksen spesifikaatiosta. Se ei määrittele, milloin ensisijainen avainarvo on annettava. Niinpä pysyvyyden tarjoaja voi tehdä sen milloin tahansa jatkuvan menetelmän kutsun ja pysyvyyden kontekstin huuhtelun välillä.
useimmissa tapauksissa sillä ei ole mitään merkitystä, jos soitat Tallenna tai jatka-menetelmää. Hibernate käyttää olioluokan nimeä ja ensisijaisen avaimen arvoa tallentaakseen olion ensimmäisen tason välimuistiin. Sen vuoksi se tarvitsee ensisijaisen avainarvon, kun se suorittaa jatkuvan menetelmän.
lähes kaikissa tilanteissa Hibernate luo ensisijaisen avaimen arvon välittömästi ja laukaisee tarvittaessa SQL-lausekkeen, kun kutsut itsepintaista tai tallentavaa menetelmää.
mutta näin ei ole, jos käytät IDENTITEETTISTRATEGIAA ja yrität säilyttää yhteisöä ilman aktiivista transaktiota tai flushmodella.KÄYTTÖOHJE. Jos kutsut itsepintaista menetelmää jossakin näistä tilanteista, Hibernate viivästyttää SQL-LISÄYSLAUSEKKEEN suorittamista ja luo väliaikaisen ensisijaisen avaimen arvon. Mutta jos soitat save-menetelmään, Hibernate suorittaa SQL INSERT-lausekkeen välittömästi ja hakee ensisijaisen avaimen arvon tietokannasta.
voit hakea sen sitten tallennusmenetelmän palautusarvona.
Author a = new Author();a.setFirstName("Thorben");a.setLastName("Janssen");Long id = (Long) em.unwrap(Session.class).save(a);
tai voit kutsua getter-menetelmää hallinnoidun yksikkösi ensisijaiseksi avainmääritteeksi, jos käytät yhteisen parlamentaarisen edustajakokouksen itsepintaista menetelmää.
Author a = new Author();a.setFirstName("Torben");a.setLastName("Janssen");em.persist(a);Long id = a.getId();
Hibernate suorittaa samat SQL-lausekkeet, kun kutsut säilytystä tai tallennusmenetelmää. Mikä ja milloin se tapahtuu, riippuu ensisijaisesta avainmuodostusstrategiastasi:
ei luotu
jos asetat ensisijaisen avaimen arvon ohjelmallisesti, esim.luonnolliseen tunnisteeseen, Hibernate suorittaa SQL-INSERTTILAUSEKKEEN vain, kun se poistaa pysyvyyskontekstin.
14:08:34,979 INFO TestPersistSaveMerge:237 - Save entity14:08:35,052 INFO TestPersistSaveMerge:240 - Commit transaction14:08:35,123 DEBUG SQL:92 - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
luotu IDENTITEETTISTRATEGIALLA
jos käytät identiteettistrategiaa ensisijaisen avaimen arvon luomiseen, Hibernaten on suoritettava lisää-lauseke, kun kutsut Tallenna tai jatka-menetelmää ensisijaisen avaimen arvon hakemiseksi tietokannasta.
14:09:28,264 INFO TestPersistSaveMerge:237 - Save entity14:09:28,336 DEBUG SQL:92 - insert into Author (firstName, lastName, version) values (?, ?, ?)14:09:28,354 INFO TestPersistSaveMerge:240 - Commit transaction
luotu SEKVENSSISTRATEGIALLA
ja jos käytät sekvenssiä, Hibernate suorittaa SQL SELECT-lausekkeen hakeakseen seuraavan arvon tietokantasekvenssistä. Hibernate sitten viivästyttää INSERTTILAUSUNTOA, kunnes se huuhtoo pysyvyyskontekstin. Tässä esimerkissä värisuora tapahtuu, kun transaktio tehdään.
14:10:27,994 INFO TestPersistSaveMerge:237 - Save entity14:10:28,002 DEBUG SQL:92 - select nextval ('hibernate_sequence')14:10:28,042 INFO TestPersistSaveMerge:240 - Commit transaction14:10:28,096 DEBUG SQL:92 - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
luotu TAULUKKOSTRATEGIALLA
ei kannata käyttää TAULUKKOSTRATEGIAA, koska se vaatii rivitason lukkoja ensisijaisessa avaintaulukossa eikä skaalaudu hyvin. Jos käytät tätä strategiaa joka tapauksessa, Hibernate suorittaa SQL SELECT-lausekkeen hakeakseen seuraavan ensisijaisen avaimen arvon tietokannasta ja kirjoittaa uuden arvon tietokantataulukkoon. Se viivästyttää SQL-LISÄYSLAUSEKKEEN suorittamista uudelle entiteetille, kunnes se huuhtoo pysyvyyskontekstin.
14:11:17,368 INFO TestPersistSaveMerge:237 - Save entity14:11:17,482 DEBUG SQL:92 - select tbl.next_val from hibernate_sequences tbl where tbl.sequence_name=? for update of tbl14:11:17,531 DEBUG SQL:92 - insert into hibernate_sequences (sequence_name, next_val) values (?,?)14:11:17,534 DEBUG SQL:92 - update hibernate_sequences set next_val=? where next_val=? and sequence_name=?14:11:17,584 INFO TestPersistSaveMerge:240 - Commit transaction14:11:17,655 DEBUG SQL:92 - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)
kumpi valitaan?
voisi olettaa, että Tallenna ja jatka-menetelmä käyttäytyy eri tavalla, koska yhteisen parlamentaarisen edustajakokouksen spesifikaation ja Hibernaten patentoitujen menetelmien javadocin välillä on muutamia eroja.
mutta lähes kaikki nämä erot häviävät, kun tarkastellaan sisäistä toteutusta. Ainoat, jotka jäävät ovat 2 kulma tapauksissa, joissa Hibernate saattaa viivästyttää hakemista ensisijainen avain, return tyyppi menetelmän ja tukea muiden JPA toteutuksia.
useimmissa sovelluksissa sillä ei ole merkitystä, saatko generoidun ensisijaisen avaimen arvon Hibernaten tallennusmenetelmän paluutyyppinä vai ensisijaisen avaimen attribuutin getter-menetelmänä. Kunhan et käytä laajennettua pysyvyyskontekstia ja suoritat kaikki tietokantaoperaatiot aktiivisella tapahtumalla, suosittelen käyttämään JPA: n itsepintaista menetelmää.
Erillisyksikön päivittäminen
kun suljet nykyisen pysyvyyskontekstin tai poistat sen eksplisiittisesti kutsumalla selkeät tai irrotettavat menetelmät EntityManager-rajapinnassa, oliosta tulee irrallinen. Tämä tarkoittaa, että sitä ei enää tallenneta 1.tason välimuistiin ja että Hibernate ei kopioi mitään sovellettuja muutoksia tietokantaan.
voit käyttää Hibernaten päivitystä tai JPA: n yhdistämismenetelmää liittääksesi irronneen olion pysyvyyskontekstiin. Kun olet tehnyt sen, Hibernate päivittää tietokannan entiteetin attribuuttiarvojen perusteella.
päivitys-ja yhdistämistavan vaikutus näyttää olevan sama, mutta kuten seuraavissa kohdissa näkyy, siinä on merkittävä ero.
yhteisen parlamentaarisen edustajakokouksen yhdistämismenetelmä
yhteisen edustajakokouksen yhdistämismenetelmä kopioi erillisyksikön tilan saman yksikön hallinnoituun esiintymään. Hibernate, siis, suorittaa SQL SELECT lauseke hakea hallittu yksikkö tietokannasta. Jos pysyvyyskontekstissa on jo hallittu olion ilmentymä, Hibernate käyttää olemassa olevaa ilmentymää sen sijaan. Sen jälkeen se kopioi kaikki attribuuttiarvot hallittuun yksikköön ja palauttaa sen soittajalle.
Author managedAuthor = em.merge(a);
kun olet aktivoinut SQL-lausekkeiden kirjaamisen, voit nähdä suoritetut SELECT-ja UPDATE-lausekkeet loki-ulostulossa.
11:37:21,172 DEBUG SQL:92 - select books0_.bookId as bookId1_2_0_, books0_.authorId as authorId2_2_0_, book1_.id as id1_1_1_, book1_.fk_author as fk_autho6_1_1_, book1_.format as format2_1_1_, book1_.publishingDate as publishi3_1_1_, book1_.title as title4_1_1_, book1_.version as version5_1_1_, author2_.id as id1_0_2_, author2_.firstName as firstNam2_0_2_, author2_.lastName as lastName3_0_2_, author2_.version as version4_0_2_ from BookAuthor books0_ inner join Book book1_ on books0_.authorId=book1_.id left outer join Author author2_ on book1_.fk_author=author2_.id where books0_.bookId=?11:37:21,180 INFO TestPersistSaveMerge:82 - Before commit11:37:21,182 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?
kun horrostila huuhtoo pysyvyyskontekstin seuraavan kerran, sen likaiset tarkastusmekanismit tarkastavat kaikki hallitut yksiköt. Jos se havaitsee yhdistämistoiminnon muuttaneen jotakin entiteetin attribuuttiarvoa, se laukaisee vaaditun SQL-PÄIVITYSLAUSEKKEEN.
on yksi tärkeä yksityiskohta, joka sinun on tiedettävä, kun käytät yhteisen parlamentaarisen edustajakokouksen yhdistämismenetelmää. Hibernate kopioi irtautuneen olion attribuuttiarvot hallittavalle entiteetille. Tämä korvaa kaikki muutokset, jotka olet tehnyt tälle entiteetille nykyisessä istunnossa.
Hibernaten päivitysmenetelmä
Hibernaten päivitysmenetelmä ei laukaise SQL SELECT-lausetta. Se vain liittää olion nykyiseen pysyvyyskontekstiin. Toisin kuin JPA: n yhdistämistapa, et voi menettää muutoksia soittamalla päivitysmenetelmään. Jos pysyvyyskontekstissa on jo hallittu instanssi entiteetistä, jonka haluat päivittää, se heittää poikkeuksen.
em.unwrap(Session.class).update(a);
kun Hibernate suorittaa seuraavan huuhtelun, se ei tee likaisia tarkastuksia. Se ei ole mahdollista, koska Hibernate Ei lukenut olion uusinta versiota tietokannasta. Se vain suorittaa SQL-päivitystiedot uudelleen kiinnitetylle kokonaisuudelle.
11:38:28,151 INFO TestPersistSaveMerge:121 - Before commit11:38:28,153 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?
puuttuva likatarkistus aiheuttaa tarpeettoman SQL-PÄIVITYSVÄITTEEN, kun olio ja vastaava tietokantatallenne sisältävät samat arvot. Tämä saattaa olla ongelma, jos DBA rekisteröi päivityskäynnistimen tietokantataulukkoon. Näissä tilanteissa voit merkitä yksikkösi merkinnällä @SelectBeforeUpdate.
@Entity@SelectBeforeUpdatepublic class Author { ... }
, joka käskee Hibernatea valitsemaan olion ja suorittamaan likaisen tarkistuksen ennen kuin se luo SQL-päivityslausekkeen. Kuten loki-ulostulosta näkyy, päivitysmenetelmän käyttäytyminen on nyt samanlainen kuin JPA: n yhdistämismenetelmä.
19:08:16,530 INFO TestPersistSaveMerge:121 - Before commit19:08:16,531 DEBUG SQL:92 - select author_.id, author_.firstName as firstNam2_0_, author_.lastName as lastName3_0_, author_.version as version4_0_ from Author author_ where author_.id=?19:08:16,592 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?
, mutta 2-menetelmien välillä on merkittävä ero. Kun soitat päivitysmenetelmää, Hibernate valitsee vain sen entiteetin, jonka annoit menetelmäparametrina. Mutta kun soitat JPA: n yhdistämistapaan, Hibernate valitsee myös kaikki assosiaatiot Cascadetypen kanssa.YHDISTÄÄ. Siksi kannattaa suosia JPA: n yhdistämistapaa, jos kiinnittää valtavan kokonaisuuksien kuvaajan uudelleen.
kumpi valitaan?
näihin kysymyksiin ei ole yleistä vastausta. Kuten olette nähneet, molemmilla menetelmillä on etunsa ja haittansa. Sinun täytyy päättää oman käyttötapauksen, jos Hibernate on valittava entiteetti ennen kuin se laukaisee SQL UPDATE-lausekkeen. Ja jos näin on, sinun täytyy myös harkita syvyys entiteetti kuvaajan ja suorituskykyä vaikutuksia edellyttäen noutaminen käyttäytymistä.
hallitun yksikön päivittäminen
yhteisen parlamentaarisen edustajakokouksen ja Hibernaten avulla hallitun yksikön päivittäminen on erittäin helppoa. Jos entiteettisi on elinkaaritilassa hallittuna, esim. siksi, että hait sen JPQL-kyselyllä tai Entitymanagerin etsi-menetelmällä, sinun tarvitsee vain muuttaa entiteettisi attribuuttien arvoja.
em = emf.createEntityManager();em.getTransaction().begin();a = em.find(Author.class, a.getId());a.setFirstName("Thorben");log.info("Before commit");em.getTransaction().commit();em.close();
kun Hibernate päättää huuhdella pysyvyyskontekstin, likainen tarkistusmekanismi havaitsee muutoksen ja suorittaa vaaditun SQL-päivityslausekkeen.
11:41:49,178 DEBUG SQL:92 - select author0_.id as id1_0_0_, author0_.firstName as firstNam2_0_0_, author0_.lastName as lastName3_0_0_, author0_.version as version4_0_0_ from Author author0_ where author0_.id=?11:41:49,191 INFO TestPersistSaveMerge:335 - Before commit11:41:49,193 DEBUG SQL:92 - update Author set firstName=?, lastName=?, version=? where id=? and version=?
sinun ei tarvitse, eikä sinun tulisi soittaa Hibernaten tallennusmenetelmään sen jälkeen, kun olet päivittänyt kokonaisuuden. Joka laukaisee ylimääräisen SaveOrUpdate tapahtuma tarjoamatta mitään etuja. Kun Hibernate päättää huuhdella pysyvyyden kontekstin, se suorittaa likaisen tarkistuksen joka tapauksessa havaitakseen kaikki muutokset ennen kuin se suorittaa vaaditut SQL-päivitystiedot.