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

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

# 実装内容
```gradle: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を返却します。

```java
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参照)

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

```java: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;
}
```


```java: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パラメータを設定する
1. ストアドプロシージャを実行する(procedureQuery.execute())
1. OutParameterを取得する
1. InOutParameterを取得する
1. 1つ目のResultSetを取得する
1. ストアドプロシージャの2つ目のResultSetを受け取るクラスを指定して、IN、OUT、INOUTパラメータを設定する
1. ストアドプロシージャを実行する(procedureQuery.hasMoreResults())
1. 2つ目のResultSetを取得する

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

# 注意点
JPAで複数のResultSetを返却するストアドプロシージャの実行例は上記の通りですが、実際に動作してみると
- procedureQuery.execute()
- procedureQuery.hasMoreResults()

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

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171963/61266bd8-fb03-d31a-debc-e8f17e6a2b1e.png" width=60%>

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

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