9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ZOZOAdvent Calendar 2022

Day 15

JPAでストアドプロシージャから複数のResultSetを受け取る

Last updated at Posted at 2022-12-14

概要

JPAでストアドプロシージャ(SQLServer)から複数のResultSetを受け取る方法です。

実装内容

build.gradle
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	runtimeOnly 'com.microsoft.sqlserver:mssql-jdbc'
}

シンプルなストアドの例

  • SingleStoredProcedureはINPUTパラメータ名がParameterで、1つのResultSetを返却します。
public interface SingleStoredProcedureRepository extends JpaRepository<SingleStoredProcedureResult, Long> {

  @Procedure(procedureName = "SingleStoredProcedure")
  List<SingleStoredProcedureResult> executeSingleStoredProcedure(@Param("Parameter") String parameter);
}

ResultSetを2つ返すストアドから取得する例

  • MultipleResutSetStoredProcedureは以下の通りです。
    • INPUTパラメータ名は InParameter
    • OUTPUTパラメータ名は OutParameter
    • INOUTPUTパラメータ名は InOutParameter
    • ResultSetは以下の2つを返却
      • FirstResult (詳細はFirstResult.java参照)
      • SecondResult (詳細はSecondResult.java参照)
public class MultipleResutSetStoredProcedureRepository {

  @PersistenceContext(unitName = "db")
  private EntityManager entityManager;

  public MultipleResutSetStoredProcedureResult executeMultipleResutSetStoredProcedure(
          String inParameter,
          String inoutParameter){
    entityManager.createStoredProcedureQuery("MultipleResutSetStoredProcedure", FirstResult.class)
            .registerStoredProcedureParameter("InParameter", String.class, ParameterMode.IN)
            .registerStoredProcedureParameter("OutParameter", String.class, ParameterMode.OUT)
            .registerStoredProcedureParameter("InOutParameter", String.class, ParameterMode.INOUT)
            .setParameter("InParameter", inParameter)
            .setParameter("InOutParameter", inOutParameter); // 1

    procedureQuery.execute(); // 2
    String outParameter = (String)procedureQuery.getOutputParameterValue("OutParameter"); // 3
    inoutParameter = (String)procedureQuery.getOutputParameterValue("InOutParameter"); // 4

    List<FirstResult> firstResultList = procedureQuery.getResultList(); // 5

    entityManager.createStoredProcedureQuery("MultipleResutSetStoredProcedure", SecondResult.class)
            .registerStoredProcedureParameter("InParameter", String.class, ParameterMode.IN)
            .registerStoredProcedureParameter("OutParameter", String.class, ParameterMode.OUT)
            .registerStoredProcedureParameter("InOutParameter", String.class, ParameterMode.INOUT)
            .setParameter("InParameter", inParameter)
            .setParameter("InOutParameter", inOutParameter); // 6

    procedureQuery.hasMoreResults(); // 7

    List<SecondResult> secondResultList = procedureQuery.getResultList(); // 8

    return new MultipleResutSetStoredProcedureResult(outParameter, inoutParameter, firstResultList, secondResultList);
  }
}
FirstResult.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class FirstResult {

  @Id
  @Column(name = "id")
  private Long id;
  @Column(name = "first_name")
  private String firstName;
}
SecondResult.java
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class SecondResult {

  @Id
  @Column(name = "id")
  private Long id;
  @Column(name = "second_type")
  private String secondType;
  @Column(name = "second_name")
  private String secondName;
}

処理の流れとしては以下の通りです。

  1. ストアドプロシージャの1つ目のResultSetを受け取るクラスを指定して、IN、OUT、INOUTパラメータを設定する
  2. ストアドプロシージャを実行する(procedureQuery.execute())
  3. OutParameterを取得する
  4. InOutParameterを取得する
  5. 1つ目のResultSetを取得する
  6. ストアドプロシージャの2つ目のResultSetを受け取るクラスを指定して、IN、OUT、INOUTパラメータを設定する
  7. ストアドプロシージャを実行する(procedureQuery.hasMoreResults())
  8. 2つ目のResultSetを取得する

メソッド名から6.の処理なしで2つ目のResultSetを取得できるようなイメージでしたが、取得できませんでした。
また、1.の第二引数は、複数のクラスを指定できるため、1つ目と2つ目のResultSetを指定して実行(procedureQuery.execute())しましたが、エラーになってしまいました。

注意点

JPAで複数のResultSetを返却するストアドプロシージャの実行例は上記の通りですが、実際に動作してみると

  • procedureQuery.execute()
  • procedureQuery.hasMoreResults()

の2箇所でDBアクセスをしています。

上記は、これまで紹介したコードを実際に動作させてAPMで取得した図です。
一番下の紫の部分がDBアクセスとなっており、左から1番目がSingleStoredProcedureを実行したものです。
2、3番目はMultipleResutSetStoredProcedureを実行したものです。

DBアクセスを1回にしたい場合は、別の方法で検証する必要がありそうです。

9
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?