sql >> データベース >  >> RDS >> Mysql

IllegalArgumentException:タイプをnullにすることはできません

    1.11.1以降のSpringDataJPAは、結果セットを返すSPをサポートしていません。 対応する欠陥 を提出しました 春のデータ付き。

    解決策は、APIレベルを下げて、JPAを使用することです。これは、MSSQLSPで動作する私が作成した汎用クラスです。

    import com.google.common.base.Strings;
    import java.util.List;
    import javax.persistence.EntityManager;
    import javax.persistence.ParameterMode;
    import javax.persistence.Query;
    import javax.persistence.StoredProcedureQuery;
    import lombok.RequiredArgsConstructor;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    @Service
    @RequiredArgsConstructor(onConstructor = @__(@Autowired))
    public class StoredProcRepository {
    
      //region Injected beans (via a RequiredArgsConstructor)
      private final EntityManager em;
      //endregion 
    
      /**
       * Calls a stored procedure via JPA and retrieves a single implicit result set (in DBs that
       * support them e.g. MS SQL or MySQL). The call is not dependent on a DB dialect. Be
       * aware that large result sets should be paginated and not entirely read to memory. Recreates
       * StoredProcedureQuery instance and its parameters on each call.
       * To execute MS SQL SPs performing multiple queries, SET NOCOUNT ON.
       *
       * @param procedureName stored procedure name, optionally qualified per DB syntax
       * @param resultClass converts (maps) each result set row into instances of resultClass via JPA
       * @param spArgs stored procedure arguments, supplied positionally (optional SP arguments at the
       * end of the list could be omitted)
       * @param <T> class of row instances converted per JPA
       * @return the entire result set
       */
      public <T> List<T> queryViaStoredProc(String procedureName, Class<T> resultClass,
          Object... spArgs) {
        StoredProcedureQuery spq = em.createStoredProcedureQuery(procedureName, resultClass);
        int pos = 0;
        for (Object arg : spArgs) {
          spq.registerStoredProcedureParameter(++pos, arg.getClass(), ParameterMode.IN);
          spq.setParameter(pos, arg);
        }
        return spq.getResultList();
      }
    
      /**
       * Calls a stored procedure via JPA and retrieves only the top row of a single implicit result
       * set (in DBs that support them e.g. MS SQL or MySQL).
       * Assumes that result set has at least one row.
       * The call is not dependent on a DB dialect.
       * Be aware that large result sets should be paginated and not entirely read to memory.
       * Recreates StoredProcedureQuery instance and its parameters on each call.
       * To execute MS SQL SPs performing multiple queries, SET NOCOUNT ON.
       *
       * @param procedureName stored procedure name, optionally qualified per DB syntax
       * @param resultClass converts (maps) each result set row into instances of resultClass via JPA
       * @param spArgs stored procedure arguments, supplied positionally (optional SP arguments at the
       * end of the list could be omitted)
       * @param <T> class of row instances converted per JPA
       * @return the entire result set
       */
      public <T> T queryTopRowViaStoredProc(String procedureName, Class<T> resultClass,
          Object... spArgs) {
        return queryViaStoredProc(procedureName, resultClass, spArgs).get(0);
      }
    }
    

    MS SQL SPの場合、追加の要件はSET NOCOUNT ONを持つことです。 複数のクエリを実行するすべてのSPに対して。これは、少なくとも3つの方法のいずれかで設定できます。

    1. JPAを使用する汎用Javaラッパー(以下のコードを参照)。このアプローチは、jTDSJDBCドライバーでのみ機能します。 対応する問題 MSJDBCドライバープロジェクトに提出されました。
    2. 各SPの冒頭。
    3. データベース内でグローバルに

    彼女は#1のコードです:同じStoredProcRepositoryの対応するメソッド クラス。

      /**
       * Calls an MS SQL stored procedure via JPA and retrieves a single implicit result set.
       * Protects against lack of SET NOCOUNT in stored procedures.
       * This works with jTDS JDBC driver, but not with MS JDBC driver.
       * Be aware that large result sets should be paginated and not entirely read to memory.
       *
       * @param procedureName stored procedure name, optionally qualified per DB syntax
       * @param resultClass converts (maps) each result set row into instances of resultClass via JPA
       * @param spArgs stored procedure arguments, supplied positionally (optional SP arguments at the
       * end of the list could be omitted)
       * @param <T> class of row instances converted per JPA
       * @return the entire result set
       */
      public <T> List<T> queryViaMsSqlStoredProc(String procedureName, Class<T> resultClass,
          Object... spArgs) {
        String spBindParams = (spArgs.length == 0) ? "" : "?" + Strings.repeat(",?", spArgs.length - 1);
    
        // The following works with jTDS driver, but not with MS driver
        String spQuery = String.format("EXEC %s %s", procedureName, spBindParams);
    
        // The following works with jTDS driver, but not with MS driver
        /*
        String spQuery = String.format("{call %s(%s)}", procedureName, spBindParams);
        Query q = em.createNativeQuery("SET NOCOUNT ON; " + spQuery, resultClass)
            .setHint("org.hibernate.readOnly", true);
        */
    
        Query q = em.createNativeQuery(spQuery, resultClass);
        int pos = 0;
        for (Object arg : spArgs) {
          q.setParameter(++pos, arg);
        }
        return q.getResultList();
      }    
    
      /**
       * Calls an MS SQL stored procedure via JPA and retrieves only the top row of a single implicit
       * result set.
       * Assumes that result set has at least one row.
       * The call sets the "NOCOUNT ON" MS SQL batch option.
       * Be aware that large result sets should be paginated and not entirely read to memory.
       *
       * @param procedureName stored procedure name, optionally qualified per DB syntax
       * @param resultClass converts (maps) each result set row into instances of resultClass via JPA
       * @param spArgs stored procedure arguments, supplied positionally (optional SP arguments at the
       * end of the list could be omitted)
       * @param <T> class of row instances converted per JPA
       * @return the entire result set
       */
      public <T> T queryTopRowViaMsSqlStoredProc(String procedureName, Class<T> resultClass,
          Object... spArgs) {
        return queryViaMsSqlStoredProc(procedureName, resultClass, spArgs).get(0);
      }
    


    1. NodeJSとPostgresを使用したトランザクションチェーンのオプションのINSERTステートメント

    2. mysqlを使用して最初のN個の*グループ*を選択します

    3. MySQLが認証タイプを標準からcaching_sha2_passwordに変更

    4. PostgreSQLベースのアプリケーションパフォーマンス:レイテンシと隠れた遅延