mybatis xml文件中 是否需要指定jdbcType


本人偷懶,不想寫jdbcType,又怕不寫導致問題,所以就對這個研究了一下。網上很多說不設置jdbcType會導致報錯,我試了一下發現都沒有報錯。
當前環境:jdk 1.8,mybatis3.2.6,mysql 8.0.19。

官方文檔說明

mybatis 官方文檔
和 MyBatis 的其它部分一樣,幾乎總是可以根據參數對象的類型確定 javaType,除非該對象是一個 HashMap。這個時候,你需要顯式指定 javaType 來確保正確的類型處理器(TypeHandler)被使用。
提示 JDBC 要求,如果一個列允許使用 null 值,並且會使用值為 null 的參數,就必須要指定 JDBC 類型(jdbcType)。閱讀 PreparedStatement.setNull()的 JavaDoc 來獲取更多信息。

我編寫了相關的 使用對象,HashMap 傳遞參數,值為null,不設置jdbcType 的情況,但是都沒有拋出異常。

既然文檔提到了PreparedStatement.setNull()方法,我們看一下。

PreparedStatement.setNull() 方法

 /**
     * Sets the designated parameter to SQL <code>NULL</code>.
     *
     * <P><B>Note:</B> You must specify the parameter's SQL type.
     *
     * @param parameterIndex the first parameter is 1, the second is 2, ...
     * @param sqlType the SQL type code defined in <code>java.sql.Types</code>
     * @exception SQLException if parameterIndex does not correspond to a parameter
     * marker in the SQL statement; if a database access error occurs or
     * this method is called on a closed <code>PreparedStatement</code>
     * @exception SQLFeatureNotSupportedException if <code>sqlType</code> is
     * a <code>ARRAY</code>, <code>BLOB</code>, <code>CLOB</code>,
     * <code>DATALINK</code>, <code>JAVA_OBJECT</code>, <code>NCHAR</code>,
     * <code>NCLOB</code>, <code>NVARCHAR</code>, <code>LONGNVARCHAR</code>,
     *  <code>REF</code>, <code>ROWID</code>, <code>SQLXML</code>
     * or  <code>STRUCT</code> data type and the JDBC driver does not support
     * this data type
     */
    void setNull(int parameterIndex, int sqlType) throws SQLException;

如果 sqlType 是 java.sql.Types中的 ARRAY,BLOB ... 等類型或JDBC driver 不支持的數據類型,會拋出SQLFeatureNotSupportedException 異常。

網上搜 如果jdbcType未設置並且值傳的是空的,會導致執行這段代碼 throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");相關的方法如下

org.apache.ibatis.type.BaseTypeHandler#setParameter 方法

   public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
    if (parameter == null) {
      if (jdbcType == null) {
        throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
      }
      try {
        ps.setNull(i, jdbcType.TYPE_CODE);
      } catch (SQLException e) {
        throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
        		"Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +
        		"Cause: " + e, e);
      }
    } else {
      setNonNullParameter(ps, i, parameter, jdbcType);
    }
  }

我debug了一下,發現是由org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters 這個方法調用的。

org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters

 public void setParameters(PreparedStatement ps) throws SQLException {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          Object value;
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
         
          if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
          typeHandler.setParameter(ps, i + 1, value, jdbcType);
        }
      }
    }
  }

從setParameters方法我們可以這段代碼 jdbcType = configuration.getJdbcTypeForNull(); 可以看出value和jdbcType為空的話,會使用默認的jdbcType,也就是JdbcType.OTHER。所以導致拋出上面提到的TypeException只有可能有兩種情況。

  1. configuration.getJdbcTypeForNull()為空。
  2. 其他方法調用 org.apache.ibatis.type.BaseTypeHandler#setParameter 方法,傳入的parameter,jdbcType都為null。(目前沒找到)

我猜想是mybatis 版本的問題的導致的,我又使用了mybatis 3.0.1版本,發現還是不會拋出異常。

所以暫時我還是不寫jdbcType。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM