Object-relational Mapping folosind JPA, Hibernate si Spring Data JPA. Persistence cu JPA

Luxoft Training
4 min readMar 10, 2022

Cel de-al doilea articol din seria noastra despre object-relational Mapping folosind JPA, Hibernate si Spring Data JPA. De data aceasta discutam despre persistenta cu JPA.

Persistenta cu JPA

Aplicatie JPA

Vom scrie o aplicatie JPA care sa salveze un item intr-o baza de date si apoi o sa il recupereze. Masina pe care ruleaza codul are instalat MySQL Release 8.0 si o baza de date numita CSCS.

Vom incepe prin instalarea si configurarea JPA, Hibernate precum si a restului de dependente. Codul sursa este sub controlul Apache Maven. Declaram aceste dependente:

Listing 1 Dependentele Maven pe Hibernate, JUnit Jupiter, si MySQL:

<dependency>

<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.4.17.Final</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>

Modulul hibernate-entitymanager include dependente tranzitive pe alte module de care vom avea nevoie precum hibernate-core si JPA interface stubs.

Avem nevoie ca dependenta junit-jupiter-engine sa ruleze testele JUnit 5, si dependenta mysql-connector-java dependency, sa ruleze driverul oficial JDBC pentru MySQL.

Vom insera persistence unit in codul nostru. Acesta contine setarile de configurare, inclusiv persistence provider, informatii legate de baza de date la care trebuie sa se conecteze, entity classes, dialectul SQL care trebuie folosit, credentiale, formatarea SQL, si altele. Aplicatiile JPA au nevoie de una sau mai multe persistence units.

Persistence unit

Fisierul persistence.xml este localizat in resources/META-INF/. Continutul arata cam asa:

Listing 2 Fisierul de configurare persistence.xml

<provider>org.hibernate.jpa.

HibernatePersistenceProvider</provider> #1
<properties>
<property name=”javax.persistence.jdbc.driver”

value=”com.mysql.cj.jdbc.Driver”/> #2
<property name=”javax.persistence.jdbc.url”

value=”jdbc:mysql://localhost:3306/CSCS”/> #3
<property name=”javax.persistence.jdbc.user”

value=”root”/> #4
<property name=”javax.persistence.jdbc.password”

value=””/> #5
<property name=”hibernate.dialect” #6

value=”org.hibernate.dialect.MySQL8Dialect”/>
<property name=”hibernate.hbm2ddl.auto”

value=”create”/> #7
</properties>

  • Din moment ce JPA este doar o specificatie, trebuie sa indicam implementarea vendor-specific PersistenceProvider a API-ului. Persistenta pe care o vom defini va fi sustinuta de catre un provider Hibernate. #1
  • Indicam proprietatile-driver JDBC #2, URL-ul bazei de date #3, username #4, si parola #5 pentru a-l accesa. Masina pe care rulam programele are MySQL 8 instalat si credentialele de acces sunt cele din persistence.xml.
  • Dialectul Hibernate este MySQL8 #6, deoarece baza de date cu care interactionam este MySQL Release 8.0.
  • De fiecare data cand programul este executat, baza de date va fi creata de la zero #7. Acest lucru este ideal pentru testarea automata cand vrem sa lucram cu o baza de date curata pentru fiecare test run.

Persistent class

Aplicatia pe care o implementam are persistent class, Item:

Listing 3 Item class

@Entity #1

public class Item {

@Id #2
@GeneratedValue #3
private Long id;

private String info; #4
}

  • Clasele persistente au nevoie de adnotarea @Entity #1, pentru a indica ca ele corespund unui tabel dintr-o baza de date. Daca nu este specificat un nume de tabel, aceasta clasa va fi mapata in mod default pe un tabel denumit ITEM.
  • Clasele persistente au nevoie de un atribut adnotat cu @Id #2, pentru a corespunde cheii primare a tabelului din baza de date. Acest atribut va fi mapat pe o coloana denumita ID.
  • Adnotarea @GeneratedValue indica generarea automata a cheilor primare #3. Pot sa fie folosite multe strategii aici, in functie de baza de date: campuri identitare, valori obtinute dintr-o secventa sau un tabel.
  • Atributele vor fi mapate pe coloanele din tabel. Din moment ce nu este specificat un nume de coloana, informatia legata de atribute #4 va fi mapata default pe o coloana numita INFO.

Salvarea si recuperarea de itemi

Hai sa salvam un Item nou in baza de date.

Listing 4 Clasa ItemJPATest

@Test
void saveRetrieveItem() {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(

“cscs”); #1

try {
EntityManager em =

emf.createEntityManager(); #2
em.getTransaction().begin(); #3
Item item = new Item(); #4
item.setInfo(“Item”); #4
em.persist(item); #5
em.getTransaction().commit(); #6
em.close(); #7

} finally {
emf.close(); #8
}
}

}

  • Avem nevoie de EntityManagerFactory pentru a accesa baza de date #1. Corespunde persistence unit pe care am definit-o anterior.
  • Cream un EntityManager si vom incepe o noua sesiune cu o baza de date #2.
  • Obtinem accesul la standard transaction API si incepem o tranzactie #3.
  • Cream o noua instanta a Item class, si setam informatiile legate de proprietate #4.
  • Transient instance devine persistenta de partea persistence context #5.
  • Angajarea tranzactiei #6. Un camp nou este inserat in tabelul ITEM. Accesul la baza de date trebuie sa fie tranzactional, chiar daca este read-only.
  • Pe masura ce cream EntityManager, trebuie sa il inchidem #7.
  • Pe masura ce am creat EntityManagerFactory, trebuie sa o inchidem #8.
  • Nu exista cod SQL si utilizare JDBC in aplicatia JPA. Nu exista operatiuni CRUD (create, read, update, delete) in codul Java, lucram doar in modul object-oriented, cu clase, obiecte, si metode. Traducerea in fiecare dialect SQL este facuta prin ORM, lucru care adreseza si portabilitatea.

Vrei sa inveti mai multe despre aceasta tehnologie? Descopera cursurile noastre.

Catalin Tudose
Java and Web Technologies Expert

Originally published at https://www.luxoft-training.ro.

--

--