Ein Leitfaden für gespeicherte Prozeduren mit JPA
1. Einführung
In diesem kurzen Tutorial werden wir die Verwendung gespeicherter Prozeduren in der Java Persistence API (JPA) untersuchen.
2. Projektaufbau
2.1. Maven Setup
Wir müssen zuerst die folgenden Abhängigkeiten in unserenpom.xml: definieren
-
javax.javaee-api - da es die JPA-API enthält
-
eine JPA-API-Implementierung - in diesem Beispiel werdenHibernate verwendet, aberEclipseLink wäre auch eine gute Alternative
-
aMySQL Datenbank
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. Definition der Persistenzeinheit
Der zweite Schritt ist die Erstellung der Dateisrc/main/resources/META-INF/persistence.xml, die die Definitionen der Persistenzeinheiten enthält:
org.hibernate.jpa.HibernatePersistenceProvider
com.example.jpa.model.Car
Alle definierten Ruhezustandseigenschaften werden nicht benötigt, wenn Sie auf eine JNDI-DataSource verweisen (JEE-Umgebungen):
java:jboss/datasources/JpaStoredProcedure
2.3. Tabellenerstellungsskript
Erstellen wir nun einTable ( CAR ) - mit drei Attributen:ID, MODEL undYEAR:
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 der gespeicherten Prozedur 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
Jetzt können Sie mit JPA mit der Datenbank kommunizieren und die von uns definierte gespeicherte Prozedur ausführen.
Sobald wir dies getan haben, können wir die Ergebnisse auch alsList vonCar. durchlaufen
3.1. DieCar-Entität
Unterhalb der EntitätCar, die vom Entitätsmanager der DatenbanktabelleCARgut zugeordnet werden kann.
Beachten Sie, dass wir unsere gespeicherte Prozedur auch direkt in der Entität mithilfe der Annotation@NamedStoredProcedureQueriesdefinieren:
@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
Nun, da alles definiert und eingerichtet ist, schreiben wir ein paar Tests, bei denen die Prozedur tatsächlich mit JPA ausgeführt wird.
Wir werden alleCars in einem gegebenenyear 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 im zweiten Testwe’re no longer using the stored procedure we defined on the entity. 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 Lernprogramm wurde die Verwendung von Stored Procedure mit der Java Persistence API erläutert.
Das in diesem Artikel verwendete Beispiel ist alssample project in GitHub verfügbar.