Eine Anleitung zu gespeicherten Prozeduren mit JPA

1. Einleitung

In diesem kurzen Tutorial werden wir die Verwendung gespeicherter Prozeduren in der Java Persistence API (JPA) untersuchen.

2. Projekteinrichtung

2.1. Maven Setup

Wir müssen zuerst die folgenden Abhängigkeiten in unserer pom.xml definieren :

  • javax.javaee-api - da es die JPA-API enthält
  • eine JPA-API-Implementierung - in diesem Beispiel verwenden wir den Ruhezustand , aber EclipseLink wäre auch eine gute Alternative
  • eine MySQL- Datenbank
 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. Definition der Persistenzeinheit

Der zweite Schritt ist die Erstellung der Datei src / main / resources / META-INF / persistence.xml , die die Definitionen der Persistenzeinheiten enthält:

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

Alle definierten Eigenschaften für den Ruhezustand werden nicht benötigt, wenn Sie auf eine JNDI DataSource (JEE-Umgebungen) verweisen:

java:jboss/datasources/JpaStoredProcedure

2.3. Tabellenerstellungsskript

Erstellen wir nun eine Tabelle (CAR) mit drei Attributen: ID, MODELL und JAHR :

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;

Die Annahme war natürlich, dass das DB-Schema und die Berechtigungen bereits vorhanden sind.

2.4. Erstellung gespeicherter Prozeduren in der Datenbank

Der allerletzte Schritt vor dem Sprung zum Java-Code ist die Erstellung gespeicherter Prozeduren in unserer MySQL-Datenbank:

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. Die gespeicherte JPA-Prozedur

Wir sind jetzt bereit, JPA zu verwenden, um mit der Datenbank zu kommunizieren und die von uns definierte gespeicherte Prozedur auszuführen.

Sobald wir das getan haben, können wir die Ergebnisse auch als Liste der Autos durchlaufen .

3.1. Das Auto Entity

Unterhalb der Car- Entität, die vom Entity Manager gut der CAR- Datenbanktabelle zugeordnet werden kann.

Beachten Sie, dass wir unsere gespeicherte Prozedur auch direkt in der Entität mithilfe der Annotation @NamedStoredProcedureQueries definieren :

@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. Zugriff auf die Datenbank

Nachdem alles definiert und eingerichtet ist, schreiben wir ein paar Tests, bei denen die Prozedur tatsächlich mit JPA ausgeführt wird.

Wir werden alle Autos in einem bestimmten Jahr abrufen :

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

Beachten Sie, dass wir im zweiten Test nicht mehr die gespeicherte Prozedur verwenden, die wir für die Entität definiert haben . Stattdessen definieren wir das Verfahren von Grund auf neu.

Dies kann sehr nützlich sein, wenn Sie gespeicherte Prozeduren verwenden müssen, aber nicht die Möglichkeit haben, Ihre Entitäten zu ändern und neu zu kompilieren.

4. Fazit

In diesem Tutorial haben wir die Verwendung gespeicherter Prozeduren mit der Java-Persistenz-API erläutert.

Das in diesem Artikel verwendete Beispiel ist als Beispielprojekt in GitHub verfügbar.