Guide sur les procédures stockées avec JPA

Guide des procédures stockées avec JPA

1. introduction

Dans ce rapide didacticiel, nous allons explorer l'utilisation des procédures stockées dans l'API Java Persistence (JPA).

2. Configuration du projet

2.1. Maven Setup

Nous devons d'abord définir les dépendances suivantes dans nospom.xml:

  • javax.javaee-api - car il inclut l'API JPA

  • une implémentation d'API JPA - dans cet exemple, nous utiliseronsHibernate, maisEclipseLink serait également une alternative correcte

  • une base de donnéesMySQL


    7.0
    11.2.0.4
    5.1.38


    
        javax
        javaee-api
        ${jee.version}
        provided
    
    
        org.hibernate
        hibernate-entitymanager
        ${hibernate.version}
    
    
        mysql
        mysql-connector-java
        ${mysql.version}
    

2.2. Définition de l'unité de persistance

La deuxième étape est la création du fichiersrc/main/resources/META-INF/persistence.xml - qui contient les définitions des unités de persistance:




    
        org.hibernate.jpa.HibernatePersistenceProvider
        com.example.jpa.model.Car
        
            
            
            
            
            
            
        
    

Toutes les propriétés Hibernate définies ne sont pas nécessaires si vous vous référez à un JNDI DataSource (environnements JEE):

java:jboss/datasources/JpaStoredProcedure

2.3. Script de création de table

Créons maintenant unTable ( CAR ) - avec trois attributs:ID, MODEL etYEAR:

CREATE TABLE `car` (
  `ID` int(10) NOT NULL AUTO_INCREMENT,
  `MODEL` varchar(50) NOT NULL,
  `YEAR` int(4) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

Bien entendu, l’hypothèse était que le schéma de base de données et les autorisations étaient déjà en place.

2.4. Création de procédure stockée sur DB

La toute dernière étape avant de passer au code Java est la création d'une procédure stockée dans notre base de données MySQL:

DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `FIND_CAR_BY_YEAR`(in p_year int)
begin
SELECT ID, MODEL, YEAR
    FROM CAR
    WHERE YEAR = p_year;
end
$$
DELIMITER ;

3. La procédure stockée JPA

Nous sommes maintenant prêts à utiliser JPA pour communiquer avec la base de données et exécuter la procédure stockée que nous avons définie.

Une fois que nous aurons fait cela, nous serons également en mesure d'itérer les résultats en tant queList deCar.

3.1. L'entitéCar

Sous l'entitéCar qui doit être bien mappée à la table de base de donnéesCAR par Entity Manager.

Notez que nous définissons également notre procédure stockée directement sur l'entité en utilisant l'annotation@NamedStoredProcedureQueries:

@Entity
@Table(name = "CAR")
@NamedStoredProcedureQueries({
  @NamedStoredProcedureQuery(
    name = "findByYearProcedure",
    procedureName = "FIND_CAR_BY_YEAR",
    resultClasses = { Car.class },
    parameters = {
        @StoredProcedureParameter(
          name = "p_year",
          type = Integer.class,
          mode = ParameterMode.IN) })
})
public class Car {

    private long id;
    private String model;
    private Integer year;

    public Car(String model, Integer year) {
        this.model = model;
        this.year = year;
    }

    public Car() {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID", unique = true, nullable = false, scale = 0)
    public long getId() {
        return id;
    }

    @Column(name = "MODEL")
    public String getModel() {
        return model;
    }

    @Column(name = "YEAR")
    public Integer getYear() {
        return year;
    }

    // standard setter methods
}

3.2. Accéder à la base de données

Maintenant, avec tout défini et en place, écrivons quelques tests en utilisant réellement JPA pour exécuter la procédure.

Nous allons récupérer tous lesCars dans unyear donné: __

public class StoredProcedureTest {

    private static EntityManagerFactory factory = null;
    private static EntityManager entityManager = null;

    @BeforeClass
    public static void init() {
        factory = Persistence.createEntityManagerFactory("jpa-db");
        entityManager = factory.createEntityManager();
    }

    @Test
    public void findCarsByYearWithNamedStored() {
        StoredProcedureQuery findByYearProcedure =
          entityManager.createNamedStoredProcedureQuery("findByYearProcedure");

        StoredProcedureQuery storedProcedure =
          findByYearProcedure.setParameter("p_year", 2015);

        storedProcedure.getResultList()
          .forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear()));
    }

    @Test
    public void findCarsByYearNoNamedStored() {
        StoredProcedureQuery storedProcedure =
          entityManager
            .createStoredProcedureQuery("FIND_CAR_BY_YEAR",Car.class)
            .registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN)
            .setParameter(1, 2015);

        storedProcedure.getResultList()
          .forEach(c -> Assert.assertEquals(new Integer(2015), ((Car) c).getYear()));
    }

}

Notez que dans le deuxième test,we’re no longer using the stored procedure we defined on the entity. Au lieu de cela, nous définissons la procédure à partir de zéro.

Cela peut être très utile lorsque vous devez utiliser des procédures stockées mais que vous n’avez pas la possibilité de modifier vos entités et de les recompiler.

4. Conclusion

Dans ce tutoriel, nous avons expliqué l'utilisation de la procédure stockée avec l'API Java Persistence.

L'exemple utilisé dans cet article est disponible en tant quesample project in GitHub.