Una guida alle procedure memorizzate con JPA

1. Introduzione

In questo breve tutorial esploreremo l'uso delle stored procedure all'interno della Java Persistence API (JPA).

2. Configurazione del progetto

2.1. Maven Setup

Per prima cosa dobbiamo definire le seguenti dipendenze nel nostro pom.xml :

  • javax.javaee-api - poiché include l'API JPA
  • un'implementazione dell'API JPA: in questo esempio useremo Hibernate , ma anche EclipseLink sarebbe un'alternativa OK
  • un database MySQL
 7.0 11.2.0.4 5.1.38    javax javaee-api ${jee.version} provided   org.hibernate hibernate-core ${hibernate.version}   mysql mysql-connector-java ${mysql.version}  

2.2. Definizione di unità di persistenza

Il secondo passo è la creazione del file src / main / resources / META-INF / persistence.xml , che contiene le definizioni delle unità di persistenza:

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

Tutte le proprietà Hibernate definite non sono necessarie se si fa riferimento a un'origine dati JNDI (ambienti JEE):

java:jboss/datasources/JpaStoredProcedure

2.3. Script per la creazione di tabelle

Creiamo ora una tabella (CAR) - con tre attributi: ID, MODEL e YEAR :

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;

Il presupposto era, ovviamente, che lo schema e le autorizzazioni del database fossero già presenti.

2.4. Creazione di stored procedure su DB

L'ultimo passaggio prima di passare al codice java è la creazione della procedura memorizzata nel nostro database 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 procedura memorizzata JPA

Ora siamo pronti per utilizzare JPA per comunicare con il database ed eseguire la procedura memorizzata che abbiamo definito.

Una volta fatto ciò, saremo anche in grado di iterare i risultati come un elenco di auto.

3.1. L' entità automobilistica

Di seguito l' entità Auto che verrà mappata alla tabella del database CAR da Entity Manager.

Si noti che stiamo anche definendo la nostra stored procedure direttamente sull'entità utilizzando l' annotazione @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. Accesso al database

Ora, con tutto definito e a posto, scriviamo un paio di test utilizzando effettivamente JPA per eseguire la procedura.

Recupereremo tutte le auto in un dato anno :

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())); } } 

Si noti che nel secondo test, non stiamo più utilizzando la stored procedure che abbiamo definito sull'entità . Invece, stiamo definendo la procedura da zero.

Ciò può essere molto utile quando è necessario utilizzare stored procedure ma non è possibile modificare le entità e ricompilarle.

4. Conclusione

In questo tutorial abbiamo discusso dell'utilizzo di Stored Procedure con Java Persistence API.

L'esempio utilizzato in questo articolo è disponibile come progetto di esempio in GitHub.