Što je JPA? Uvod u API postojanosti Java

Kao specifikacija, Java Perzistentni API bavi se postojanošću , što podrazumijeva bilo koji mehanizam pomoću kojeg Java objekti nadživljavaju aplikacijski proces koji ih je stvorio. Ne trebaju se održavati svi Java objekti, ali većina aplikacija zadržava ključne poslovne objekte. JPA specifikacija omogućuje definiranje koji predmeti trebaju biti uporan, i kako se ti predmeti trebaju biti ustrajni u Java aplikacije.

JPA sam po sebi nije alat ili okvir; nego definira skup koncepata koji se mogu implementirati bilo kojim alatom ili okvirom. Iako se model JPA objektno-relacijskog mapiranja (ORM) izvorno zasnivao na hibernaciji, od tada je evoluirao. Isto tako, dok je JPA izvorno bio namijenjen uporabi s relacijskim / SQL bazama podataka, neke su implementacije JPA proširene za uporabu s NoSQL trgovinama podataka. Popularni okvir koji podržava JPA s NoSQL-om je EclipseLink, referentna implementacija za JPA 2.2.

JPA 2.2 u Jakarti EE

API za trajnost Java prvi je put objavljen kao podskup specifikacije EJB 3.0 (JSR 220) u Javi EE 5. Otada se razvio kao vlastita specifikacija, počevši od izdanja JPA 2.0 u Javi EE 6 (JSR 317). Od pisanja ovog članka, JPA 2.2 prihvaćen je za nastavak kao dio Jakarte EE.

JPA i Hibernate

Zbog njihove isprepletene povijesti Hibernate i JPA često se povezuju. Međutim, poput specifikacije Java Servlet, JPA je iznjedrila mnoge kompatibilne alate i okvire; Hibernate je samo jedan od njih.

Hibernate je ORM biblioteka za Javu, razvio Gavin King i objavljen početkom 2002. godine. King je razvio Hibernate kao alternativu grahu entiteta za ustrajnost. Okvir je bio toliko popularan i toliko potreban u to vrijeme da su mnoge njegove ideje usvojene i kodificirane u prvoj specifikaciji JPA.

Danas je Hibernate ORM jedna od najzrelijih JPA implementacija i još uvijek popularna opcija za ORM u Javi. Hibernate ORM 5.3.8 (trenutna verzija na ovaj članak) implementira JPA 2.2. Uz to, obitelj alata Hibernate proširila se na popularne alate poput Hibernate Search, Hibernate Validator i Hibernate OGM, koji podržavaju postojanost modela domene za NoSQL.

JPA i EJB

Kao što je ranije spomenuto, JPA je predstavljen kao podskup EJB 3.0, ali se od tada razvio kao vlastita specifikacija. EJB je specifikacija s drugačijim fokusom od JPA, a implementirana je u EJB spremnik. Svaki spremnik EJB uključuje sloj postojanosti, koji je definiran JPA specifikacijom.

Što je Java ORM?

Iako se razlikuju u izvedbi, svaka implementacija JPA pruža neku vrstu ORM sloja. Da biste razumjeli JPA i alate kompatibilne s JPA, morate dobro razumjeti ORM.

Objektno-relacijsko mapiranje je zadatak - onaj za kojeg programeri imaju dobar razlog da izbjegavaju ručno raditi. Okvir poput Hibernate ORM ili EclipseLink kodificira taj zadatak u knjižnicu ili okvir, ORM sloj . Kao dio arhitekture aplikacije, sloj ORM odgovoran je za upravljanje pretvorbom softverskih objekata radi interakcije s tablicama i stupcima u relacijskoj bazi podataka. U Javi sloj ORM pretvara Java klase i objekte tako da se mogu pohraniti i njima upravljati u relacijskoj bazi podataka.

Prema zadanim postavkama, naziv objekta koji se održava postaje naziv tablice, a polja postaju stupci. Jednom kada je tablica postavljena, svaki redak tablice odgovara objektu u aplikaciji. Mapiranje objekata je moguće konfigurirati, ali zadane vrijednosti obično rade dobro.

JPA s NoSQL-om

Do nedavno, nerelacijske baze podataka bile su neobična zanimljivost. Pokret NoSQL promijenio je sve to, a sada su raznovrsne baze podataka NoSQL dostupne programerima Java. Neke su implementacije JPA evoluirale kako bi prihvatile NoSQL, uključujući Hibernate OGM i EclipseLink.

Slika 1 prikazuje ulogu JPA i ORM sloja u razvoju aplikacija.

JavaWorld /

Konfiguriranje Java ORM sloja

Kada postavljate novi projekt za korištenje JPA, morat ćete konfigurirati podatkovnu trgovinu i pružatelja JPA. Konfigurirat ćete konektor datastore za povezivanje s odabranom bazom podataka (SQL ili NoSQL). Također ćete uključiti i konfigurirati JPA davatelja , koji je okvir poput Hibernate ili EclipseLink. Iako JPA možete konfigurirati ručno, mnogi programeri odlučuju se na korištenje Springove gotove podrške. Pogledajte " Instalacija i postavljanje JPA " u nastavku za demonstraciju ručne i JPA instalacije i postavljanja na temelju proljeća.

Java Data Objekti

Java Data Objects standardizirani je okvir trajnosti koji se razlikuje od JPA prvenstveno podržavanjem logike trajanja u objektu i dugogodišnjom podrškom za rad s nerelacijskim spremištima podataka. JPA i JDO dovoljno su slični da pružatelji usluga JDO često podržavaju JPA. Pogledajte Apache JDO projekt da biste saznali više o JDO u odnosu na druge standarde postojanosti poput JPA i JDBC.

Trajnost podataka u Javi

Iz programske perspektive, ORM sloj je prilagodbeni sloj : prilagođava jezik objektnih grafova jeziku SQL-a i relacijskih tablica. Sloj ORM omogućuje objektno orijentiranim programerima da izgrade softver koji zadržava podatke bez napuštanja objektno orijentirane paradigme.

Kada koristite JPA, iz mape podataka stvarate mapu do objekata podatkovnog modela vaše aplikacije. Umjesto definiranja načina na koji se objekti spremaju i dohvaćaju, definirate mapiranje između objekata i baze podataka, a zatim pozivate JPA da ih nastavi. Ako koristite relacijsku bazu podataka, velikim dijelom stvarne veze između vašeg aplikacijskog koda i baze podataka tada će upravljati JDBC, Java Database Connectivity API.

Kao specifikacija, JPA nudi bilješke metapodataka koje koristite za definiranje mapiranja između objekata i baze podataka. Svaka implementacija JPA pruža svoj mehanizam za bilješke JPA. JPA specifikacije također pružaju PersistanceManagerili EntityManager, koje su ključne dodirne točke s JPA sustavom (pri čemu vaš kôd poslovne logike kaže sustavu što treba učiniti s mapiranim objektima).

Da biste sve ovo učinili konkretnijim, razmotrite Popis 1, koji je jednostavna klasa podataka za modeliranje glazbenika.

Popis 1. Jednostavna klasa podataka u Javi

 public class Musician { private Long id; private String name; private Instrument mainInstrument; private ArrayList performances = new ArrayList(); public Musician( Long id, String name){ /* constructor setters... */ } public void setName(String name){ this.name = name; } public String getName(){ return this.name; } public void setMainInstrument(Instrument instr){ this.instrument = instr; } public Instrument getMainInstrument(){ return this.instrument; } // ...Other getters and setters... } 

MusicianKlasa u Listing 1 se koristi za držanje podataka. Može sadržavati primitivne podatke poput polja imena . Također može imati veze s drugim klasama kao što su mainInstrumenti performances.

Musician„S razlog postojanja je da sadrži podatke. Ova vrsta klase ponekad je poznata kao DTO ili objekt prijenosa podataka . DTO-ovi su uobičajena značajka razvoja softvera. Iako sadrže mnoge vrste podataka, ne sadrže nikakvu poslovnu logiku. Postojanje podatkovnih objekata sveprisutan je izazov u razvoju softvera.

Perzistentnost podataka s JDBC

Jedan od načina za spremanje instance Musicianklase u relacijsku bazu podataka bio bi korištenje JDBC knjižnice. JDBC je sloj apstrakcije koji aplikaciji omogućuje izdavanje SQL naredbi bez razmišljanja o temeljnoj implementaciji baze podataka.

Popis 2 pokazuje kako biste mogli ustrajati na Musiciannastavi koristeći JDBC.

Popis 2. JDBC umetanje zapisa

 Musician georgeHarrison = new Musician(0, "George Harrison"); String myDriver = "org.gjt.mm.mysql.Driver"; String myUrl = "jdbc:mysql://localhost/test"; Class.forName(myDriver); Connection conn = DriverManager.getConnection(myUrl, "root", ""); String query = " insert into users (id, name) values (?, ?)"; PreparedStatement preparedStmt = conn.prepareStatement(query); preparedStmt.setInt (1, 0); preparedStmt.setString (2, "George Harrison"); preparedStmt.setString (2, "Rubble"); preparedStmt.execute(); conn.close(); // Error handling removed for brevity 

Kôd iz popisa 2 prilično se sam dokumentira. georgeHarrisonObjekt može doći iz bilo kojeg mjesta (front-end podnijeti, vanjske usluge, itd), a njegovi polja ID i ime postaviti. Tada se polja na objektu koriste za dobavu vrijednosti SQL insertizraza. ( PreparedStatementKlasa je dio JDBC-a, nudeći način za sigurnu primjenu vrijednosti na SQL upit.)

Iako JDBC omogućuje kontrolu koja dolazi s ručnom konfiguracijom, nezgodna je u usporedbi s JPA. Da biste izmijenili bazu podataka, prvo morate stvoriti SQL upit koji se preslikava iz vašeg Java objekta u tablice u relacijskoj bazi podataka. Zatim morate izmijeniti SQL kad god se promijeni potpis objekta. S JDBC-om održavanje SQL-a postaje zadatak sam po sebi.

Perzistentnost podataka s JPA

Sada razmotrite Popis 3, gdje nastavljamo s Musiciankorištenjem klase JPA.

Popis 3. Ustrajavanje Georgea Harrisona u JPA-i

 Musician georgeHarrison = new Musician(0, "George Harrison"); musicianManager.save(georgeHarrison); 

Popis 3 zamjenjuje ručni SQL s popisa 2 jednim retkom session.save(), koji JPA-u nalaže da nastavi s postojanjem objekta. Od tada, SQL pretvorbom upravlja okvir, tako da nikada ne morate napustiti objektno orijentiranu paradigmu.

Bilješke metapodataka u JPA

Magija u Popisu 3 rezultat je konfiguracije koja se kreira pomoću JPA-ovih bilješki. Programeri koriste bilješke kako bi obavijestili JPA koji bi objekti trebali postojati i kako ih treba održavati.

Popis 4 prikazuje Musicianrazred s jednom JPA bilješkom.

Popis 4. JPA-ova bilješka @Entity

 @Entity public class Musician { // ..class body } 

Persistent objects are sometimes called entities. Attaching @Entity to a class like Musician informs JPA that this class and its objects should be persisted.

XML vs. annotation-based configuration

JPA also supports using external XML files, instead of annotations, to define class metadata. But why would you do that to yourself?

Configuring JPA

Like most modern frameworks, JPA embraces coding by convention (also known as convention over configuration), in which the framework provides a default configuration based on industry best practices. As one example, a class named Musician would be mapped by default to a database table called Musician.

The conventional configuration is a timesaver, and in many cases it works well enough. It is also possible to customize your JPA configuration. As an example, you could use JPA's @Table annotation to specify the table where the Musician class should be stored.

Listing 5. JPA's @Table annotation

 @Entity @Table(name="musician") public class Musician { // ..class body } 

Listing 5 tells JPA to persist the entity (Musician class) to the musician table.

Primary key

In JPA, the primary key is the field used to uniquely identify each object in the database. The primary key is useful for referencing and relating objects to other entities. Whenever you store an object in a table, you will also specify the field to use as its primary key.

In Listing 6, we tell JPA what field to use as Musician's primary key.

Listing 6. Specifying the primary key

 @Entity public class Musician { @Id private Long id; 

In this case, we've used JPA's @Id annotation to specify the id field as Musician's primary key. By default, this configuration assumes the primary key will be set by the database--for instance, when the field is set to auto-increment on the table.

JPA supports other strategies for generating an object's primary key. It also has annotations for changing individual field names. In general, JPA is flexible enough to adapt to any persistence mapping you might need.

CRUD operations

Once you've mapped a class to a database table and established its primary key, you have everything you need to create, retrieve, delete, and update that class in the database. Calling session.save() will create or update the specified class, depending on whether the primary-key field is null or applies to en existing entity. Calling entityManager.remove() will delete the specified class.

Entity relationships in JPA

Simply persisting an object with a primitive field is only half the equation. JPA also has the capability to manage entities in relation to one another. Four kinds of entity relationships are possible in both tables and objects:

    1. One-to-many
    2. Many-to-one
    3. Many-to-many
    4. One-to-one

Each type of relationship describes how an entity relates to other entities. For example, the Musician entity could have a one-to-many relationship with Performance, an entity represented by a collection such as List or Set.

If the Musician included a Band field, the relationship between these entities could be many-to-one, implying collection of Musicians on the single Band class. (Assuming each musician only performs in a single band.)

If Musician included a BandMates field, that could represent a many-to-many relationship with other Musician entities.

Konačno, Musicianmože imati jedan-na-jedan odnos s Quoteentiteta, a koristi se predstavljaju poznati citat: Quote famousQuote = new Quote().

Utvrđivanje vrsta odnosa

JPA ima bilješke za svaki od svojih tipova mapiranja odnosa. Popis 7 pokazuje kako možete komentirati odnos jedan-prema-više između Musiciani Performance.

Popis 7. Bilježenje odnosa jedan prema više