Is it possible to pass a null parameter to a stored procedure in Java JPA 2.1?

前端 未结 13 1758
孤城傲影
孤城傲影 2020-12-08 15:07

Using the new JPA 2.1 stored procedure call, is there any way to pass a null parameter?

Here is an example usage:

StoredProcedureQuery storedProcedur         


        
13条回答
  •  伪装坚强ぢ
    2020-12-08 15:40

    Here are my findings for Hibernate 4.3 which are relevant to JPA 2.1.

    This will throw an exception if the DB does not support default parameters:

    ProcedureCall procedure = getSession().createStoredProcedureCall("my_procedure");
    
    procedure.registerParameter("my_nullable_param", String.class, ParameterMode.IN)
             .bindValue(null);
    
    // execute
    procedure.getOutputs();
    

    From Hibernate's source for binding the parameter to the underlying CallableStatement:

    public abstract class AbstractParameterRegistrationImpl {
    
      ..
    
      @Override
      public void prepare(CallableStatement statement, int startIndex) throws SQLException {
    
        if ( mode == ParameterMode.INOUT || mode == ParameterMode.IN ) {
          if ( bind == null || bind.getValue() == null ) {
            // the user did not bind a value to the parameter being processed.  That might be ok *if* the
            // procedure as defined in the database defines a default value for that parameter.
            // Unfortunately there is not a way to reliably know through JDBC metadata whether a procedure
            // parameter defines a default value.  So we simply allow the procedure execution to happen
            // assuming that the database will complain appropriately if not setting the given parameter
            // bind value is an error.
            log.debugf("Stored procedure [%s] IN/INOUT parameter [%s] not bound; assuming procedure defines default value", procedureCall.getProcedureName(), this);
          } else {
             typeToUse.nullSafeSet( statement, bind.getValue(), startIndex, session() );
          }
        }
      }
    
      ..
    }
    

    The above comment reads:

    The user did not bind a value to the parameter being processed. That might be ok if the procedure as defined in the database defines a default value for that parameter. Unfortunately there is not a way to reliably know through JDBC metadata whether a procedure parameter defines a default value. So we simply allow the procedure execution to happen assuming that the database will complain appropriately if not setting the given parameter bind value is an error.

    I am interpreting that as JPA (specifically Hibernate) DOES NOT support setting null parameters at all. It looks like they are in a struggle with supporting default parameter values versus substituting a null value when appropriate. They choose to support the former. It looks like those who need support for the latter (nullable values) must use java.sql.CallableStatement:

    getSession().doWork(new Work() {
    
      @Override
      public void execute(Connection conn) throws SQLException {
    
        CallableStatement stmt = conn.prepareCall("{ call my_prodecure(:my_nullable_param) }");
    
        if(stringVariableThatIsNull != null) {
           stmt.setString("my_nullable_param", stringVariableThatIsNull);
        } else {
           stmt.setNull("my_nullable_param", Types.VARCHAR);
        }
    
        stmt.execute();
        stmt.close();
    
      }    
    });
    

    tl;dr we are still forced to deal with low-level JDBC because neither JPA or Hibernate seem to address nullable parameters. They are supporting procedure parameter default values over substituting a null value.

提交回复
热议问题