Ein Leitfaden für gespeicherte Prozeduren mit JPA

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.