Recherche…


Remarques

JPA est l'API Java Persistence, une spécification gérant le mappage des objets Java et leurs relations avec une base de données relationnelle. C'est ce qu'on appelle un mappeur objet-relationnel (ORM). C'est une alternative pour (ou compléter) les JDBC de plus bas niveau. Il est très utile pour une approche orientée Java et lorsque des graphes d’objet complexes doivent être conservés.

JPA en soi n'est pas une implémentation. Vous aurez besoin d'un fournisseur de persistance pour cela (voir les exemples). Les implémentations actuelles de la dernière norme JPA 2.1 sont EclipseLink (également l'implémentation de référence de JPA 2.1, ce qui signifie "la preuve que la spécification peut être implémentée"); Hibernate et DataNucleus .

Métadonnées

Le mappage entre les objets Java et les tables de base de données est défini via des métadonnées de persistance . Le fournisseur JPA utilisera les informations de métadonnées de persistance pour effectuer les opérations de base de données correctes. JPA définit généralement les métadonnées via des annotations dans la classe Java.

Architecture d'entité objet-relationnelle

L'architecture d'entité est composée de:

  • entités
  • unités de persistance
  • contextes de persistance
  • usines de gestionnaire d'entités
  • gestionnaires d'entités

Versions

Version Groupe d'experts Libération
1.0 JSR-220 2006-11-06
2.0 JSR-317 2009-12-10
2.1 JSR-338 2013-05-22

Installation ou configuration

Exigences de Classpath

Les API Eclipselink et JPA doivent être incluses. Exemple de dépendances Maven:

<dependencies>
  <dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.6.3</version>
  </dependency>
  <dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>javax.persistence</artifactId>
    <version>2.1.1</version>
  </dependency>
  <!-- ... -->
</dependencies>

Hiberner

Hibernate-core est requis. Exemple de dépendance Maven:

<dependencies>
  <dependency>
    <!-- requires Java8! -->
    <!-- as of 5.2, hibernate-entitymanager is merged into hibernate-core -->
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.2.1.Final</version>
  </dependency>
  <dependency>
    <groupId>org.hibernate.javax.persistence</groupId>
    <artifactId>hibernate-jpa-2.1-api</artifactId>
    <version>1.0.0</version>
  </dependency>
  <!-- ... -->
</dependencies>

DataNucleus

datanucleus-core, datanucleus-api-jpa et datanucleus-rdbms (lors de l'utilisation de datastores RDBMS) sont requis. Exemple de dépendance Maven:

<dependencies>
  <dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-core</artifactId>
    <version>5.0.0-release</version>
  </dependency>
  <dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-api-jpa</artifactId>
    <version>5.0.0-release</version>
  </dependency>
  <dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>datanucleus-rdbms</artifactId>
    <version>5.0.0-release</version>
  </dependency>
  <dependency>
    <groupId>org.datanucleus</groupId>
    <artifactId>javax.persistence</artifactId>
    <version>2.1.2</version>
  </dependency>
  <!-- ... -->
</dependencies>

Détails de la configuration

JPA nécessite l'utilisation d'un fichier persistence.xml , situé sous META-INF à la racine de CLASSPATH. Ce fichier contient une définition des unités de persistance disponibles à partir desquelles JPA peut fonctionner.

JPA permet en outre d'utiliser un fichier de configuration de mappage orm.xml , également placé sous META-INF . Ce fichier de mappage permet de configurer la manière dont les classes sont mappées à la banque de données et constitue une alternative / un complément à l'utilisation des annotations Java dans les classes d'entités JPA elles-mêmes.

Exemple minimal de persistence.xml

Hibernate (et H2 DB intégrée)

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                             http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"
         version="2.1">

<persistence-unit name="persistenceUnit">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <class>my.application.entities.MyEntity</class>
    
    <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" /> 
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:data/myDB.db" /> 
        <property name="javax.persistence.jdbc.user" value="sa" /> 

        <!-- DDL change options -->
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create"/>

        <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
        <property name="hibernate.flushMode" value="FLUSH_AUTO" /> 
    </properties>
</persistence-unit>
</persistence>
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                             http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"
         version="2.1">

<persistence-unit name="persistenceUnit">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

    <class>my.application.entities.MyEntity</class>
    
    <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:data/myDB.db"/>
        <property name="javax.persistence.jdbc.user" value="sa"/>

        <!-- Schema generation : drop and create tables -->
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create-tables" />
    </properties>
</persistence-unit>

</persistence>

DataNucleus (et la base de données H2 intégrée)

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
                             http://java.sun.com/xml/ns/persistence/persistence_2_1.xsd"
         version="2.1">

<persistence-unit name="persistenceUnit">
    <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>

    <class>my.application.entities.MyEntity</class>
    
    <properties>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:data/myDB.db"/>
        <property name="javax.persistence.jdbc.user" value="sa"/>

        <!-- Schema generation : drop and create tables -->
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create-tables" />
    </properties>
</persistence-unit>

</persistence>

Bonjour le monde

Voyons tout le composant de base pour créer un monde Hallo simple.

  1. Définir quelle implémentation de JPA 2.1 nous utiliserons
  2. Construire la connexion à la base de données en créant l' persistence-unit
  3. Implémente les entités
  4. Implémente DAO (objet d'accès aux données) pour manipuler les entités
  5. Tester l'application

Bibliothèques

En utilisant maven, nous avons besoin de ces dépendances:

<dependencies>

    <!-- JPA is a spec, I'll use the implementation with HIBERNATE -->
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>5.2.6.Final</version>
    </dependency>

    <!-- JDBC Driver, use in memory DB -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>1.4.193</version>
    </dependency>

</dependencies>

Unité de persistance

Dans le dossier des ressources, nous devons créer un fichier appelé persistence.xml . La façon la plus simple de le définir est la suivante:

<persistence-unit name="hello-jpa-pu" transaction-type="RESOURCE_LOCAL">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>

    <properties>
        <!-- ~ = relative to current user home directory -->
        <property name="javax.persistence.jdbc.url" value="jdbc:h2:./test.db"/>
        <property name="javax.persistence.jdbc.user" value=""/>
        <property name="javax.persistence.jdbc.password" value=""/>
        <property name="javax.persistence.jdbc.driver" value="org.h2.Driver"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/>
        <property name="hibernate.show_sql" value="true"/>

        <!-- This create automatically the DDL of the database's table -->
        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>

    </properties>
</persistence-unit>

Implémenter une entité

Je crée une classe Biker :

package it.hello.jpa.entities;


import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

@Entity
@Table(name = "BIKER")
public class Biker implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "bikerName")
    private String name;

    @Column(unique = true, updatable = false)
    private String battleName;

    private Boolean beard;

    @Temporal(TemporalType.DATE)
    private Date birthday;

    @Temporal(TemporalType.TIME)
    private Date registrationDate;

    @Transient // --> this annotiation make the field transient only for JPA
    private String criminalRecord; 

    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getBattleName() {
        return battleName;
    }

    public void setBattleName(String battleName) {
        this.battleName = battleName;
    }

    public Boolean getBeard() {
        return this.beard;
    }

    public void setBeard(Boolean beard) {
        this.beard = beard;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public Date getRegistrationDate() {
        return registrationDate;
    }

    public void setRegistrationDate(Date registrationDate) {
        this.registrationDate = registrationDate;
    }

    public String getCriminalRecord() {
        return criminalRecord;
    }

    public void setCriminalRecord(String criminalRecord) {
        this.criminalRecord = criminalRecord;
    }
}

Implémenter un DAO

package it.hello.jpa.business;

import it.hello.jpa.entities.Biker;

import javax.persistence.EntityManager;
import java.util.List;

public class MotorcycleRally {

    public Biker saveBiker(Biker biker) {
        EntityManager em = EntityManagerUtil.getEntityManager();
        em.getTransaction().begin();
        em.persist(biker);
        em.getTransaction().commit();
        return biker;
    }

}

EntityManagerUtil est un singleton:

package it.hello.jpa.utils;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class EntityManagerUtil {

    // USE THE SAME NAME IN persistence.xml!
    public static final String PERSISTENCE_UNIT_NAME = "hello-jpa-pu";

    private static EntityManager entityManager;

    private EntityManagerUtil() {
    }

    public static EntityManager getEntityManager() {
        if (entityManager == null) {
            // the same in persistence.xml
            EntityManagerFactory emFactory = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME);


            return emFactory.createEntityManager();
        }
        return entityManager;
    }
}

Tester l'application

paquet it.hello.jpa.test;

classe publique TestJpa {

@Test
public void insertBiker() {
    MotorcycleRally crud = new MotorcycleRally();

    Biker biker = new Biker();
    biker.setName("Manuel");
    biker.setBeard(false);

    biker = crud.saveBiker(biker);

    Assert.assertEquals(biker.getId(), Long.valueOf(1L));
}

}

Le résultat sera:

Lancer it.hello.jpa.test.TestJpa Hibernate: drop table BIKER si existe Hibernate: drop séquence if existe hibernate_sequence Hibernate: créer la séquence hibernate_sequence démarrer avec 1 incrément de 1 ), beard boolean, date anniversaire, bikerName varchar (255), heure de registrationDate, clé primaire (id)) Hibernate: alter table BIKER ajouter une contrainte UK_a64ce28nywyk8wqrvfkkuapli unique (battleName) , id) valeurs (?,?,?,?,?,?) mar. 01, 2017 11:00:02 org.hibernate.jpa.internal.util.LogHelper logPersistenceUnitInformation INFO: HHH000204: Traitement de PersistenceUnitInfo [name: hello- jpa-pu ...] Résultats:

Tests réalisés: 1, échecs: 0, erreurs: 0, ignorés: 0



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow