JPAによるストアドプロシージャの手引き

1前書き

このクイックチュートリアルでは、Java Persistence API(JPA)内のストアドプロシージャの使用方法を探ります。

2プロジェクト設定

2.1. Mavenのセットアップ

まず、 __ pom.xml に次の依存関係を定義する必要があります。

  • javax.javaee-api - JPA APIを含むため

  • JPA APIの実装 - この例では Hibernate を使います。

しかし EclipseLink も同様に問題ありません a MySQL ** データベース

<properties>
    <jee.version>7.0</jee.version>
    <mysql.version>11.2.0.4</mysql.version>
    <hibernate.version>5.1.38</hibernate.version>
</properties>
<dependencies>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>${jee.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-entitymanager</artifactId>
        <version>${hibernate.version}</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
</dependencies>

2.2. 持続性ユニットの定義

2番目のステップは、 persistence.xml ファイルの作成です。このファイルには、持続性ユニットの定義が含まれています。

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
    http://java.sun.com/xml/ns/persistence/persistence__2__1.xsd"
    version="2.1">

    <persistence-unit name="jpa-db">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <class>com.baeldung.jpa.model.Car</class>
        <properties>
            <property name="javax.persistence.jdbc.driver"
              value="com.mysql.jdbc.Driver"/>
            <property name="javax.persistence.jdbc.url"
              value="jdbc:mysql://127.0.0.1:3306/baeldung"/>
            <property name="javax.persistence.jdbc.user"
              value="baeldung"/>
            <property name="javax.persistence.jdbc.password"
              value="YourPassword"/>
            <property name="hibernate.dialect"
              value="org.hibernate.dialect.MySQLDialect"/>
            <property name="hibernate.show__sql" value="true"/>
        </properties>
    </persistence-unit>

</persistence>

JNDIデータソース(JEE環境)を参照する場合、定義されているすべてのHibernateプロパティは必要ありません。

<jta-data-source>java:jboss/datasources/JpaStoredProcedure</jta-data-source>

2.3. テーブル作成スクリプト

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;

当然のことながら、DBスキーマとパーミッションはすでに設定されています。

2.4. DB でのストアドプロシージャの作成

Javaコードにジャンプする前の最後のステップは、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 JPAストアドプロシージャ

これでJPAを使用してデータベースと通信し、定義したストアドプロシージャを実行する準備が整いました。

そうすれば、結果を List of Car. として反復処理することもできます。

3.1. Car エンティティ

Entity Managerによって CAR データベーステーブルに正しくマップされた Car エンティティの下。

  • @ 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. データベースへのアクセス

では、すべてを定義して適切に配置した後、実際にJPAを使用してプロシージャを実行する2、3のテストを作成しましょう。

与えられた 内のすべての Cars を取得します。

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

}

2番目のテストでは、 エンティティで定義したストアドプロシージャはもう使用されていません 。代わりに、手順を最初から定義しています。

ストアドプロシージャを使用する必要があるがエンティティを変更してそれらを再コンパイルすることができない場合は、これは非常に便利です。

4結論

このチュートリアルでは、Java Persistence APIを使用したスト​​アドプロシージャの使用について説明しました。

この記事で使われている例はhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/java-jpa[GitHubのサンプルプロジェクト]として入手できます。