mybatis/mybatis-3 · error · ExecutorException

No type handler found for '" + javaType + "' and JDBC type '

Error message

No type handler found for '" + javaType + "' and JDBC type '" + rsw.getJdbcType(column) + "'"

What it means

While applying a resultMapping, MyBatis found no TypeHandler able to convert the column's JDBC value to the property's Java type. The mapping did not pin a typeHandler, so the registry lookup with the property's Java type plus the JDBC type of the column (reported in the message) returned null.

Source

Thrown at src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java:604

      return getNestedQueryMappingValue(rsw, metaResultObject, propertyMapping, lazyLoader, columnPrefix);
    }
    if (JdbcType.CURSOR.equals(propertyMapping.getJdbcType())) {
      List<Object> results = getNestedCursorValue(rsw, propertyMapping, columnPrefix);
      linkObjects(metaResultObject, propertyMapping, results.get(0), true);
      return metaResultObject.getValue(propertyMapping.getProperty());
    }
    if (propertyMapping.getResultSet() != null) {
      addPendingChildRelation(rs, metaResultObject, propertyMapping); // TODO is that OK?
      return DEFERRED;
    } else {
      final String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);
      TypeHandler<?> typeHandler = propertyMapping.getTypeHandler();
      if (typeHandler == null) {
        final String property = propertyMapping.getProperty();
        final Type javaType = property == null ? null : metaResultObject.getGenericSetterType(property).getKey();
        typeHandler = rsw.getTypeHandler(javaType, column);
        if (typeHandler == null) {
          throw new ExecutorException(
              "No type handler found for '" + javaType + "' and JDBC type '" + rsw.getJdbcType(column) + "'");
        }
      }
      return typeHandler.getResult(rs, column);
    }
  }

  private List<Object> getNestedCursorValue(ResultSetWrapper rsw, ResultMapping propertyMapping,
      String parentColumnPrefix) throws SQLException {
    final String column = prependPrefix(propertyMapping.getColumn(), parentColumnPrefix);
    ResultMap nestedResultMap = resolveDiscriminatedResultMap(rsw,
        configuration.getResultMap(propertyMapping.getNestedResultMapId()),
        getColumnPrefix(parentColumnPrefix, propertyMapping));
    ResultSetWrapper nestedRsw = new ResultSetWrapper(rsw.getResultSet().getObject(column, ResultSet.class),
        configuration);
    List<Object> results = new ArrayList<>();
    handleResultSet(nestedRsw, nestedResultMap, results, null);
    return results;

View on GitHub (pinned to 008069adb1)

Solutions

  1. Register a TypeHandler for the exact javaType/JdbcType pair: configuration.getTypeHandlerRegistry().register(MyType.class, JdbcType.X, new MyHandler())
  2. Or specify the handler inline on the mapping: <result property="p" column="c" typeHandler="com.example.MyHandler"/>
  3. Change the property to a supported Java type (String, LocalDate on 3.4.5+) and convert in a setter
  4. Upgrade MyBatis — newer versions ship handlers for more java.time and enum combinations

Example fix

<!-- before -->
<result property="created" column="created_at" javaType="java.time.Instant"/>
<!-- after -->
<result property="created" column="created_at" javaType="java.time.Instant"
        typeHandler="org.apache.ibatis.type.InstantTypeHandler"/>
Defensive patterns

Strategy: validation

Validate before calling

// Before running, confirm a handler exists for the pair
TypeHandlerRegistry thr = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
TypeHandler<?> h = thr.getTypeHandler(Year.class, JdbcType.INTEGER);
if (h == null || h instanceof UnknownTypeHandler) { thr.register(Year.class, JdbcType.INTEGER, new YearTypeHandler()); }

Try / catch

try { session.selectList("sel.statements"); } catch (ExecutorException e) { if (e.getMessage() != null && e.getMessage().contains("No type handler found")) { register handler from the message's java/jdbc pair and retry once; } else throw e; }

Prevention

When it happens

Trigger: getPropertyMappingValue with propertyMapping.getTypeHandler()==null and rsw.getTypeHandler(javaType, column) returning null — e.g. mapping an exotic javaType (some custom enum-ish type, java.time type in old versions) to an unusual JDBC type, or an enum property against a column with no string/numeric handler match.

Common situations: Mapping java.time.Instant/Year/ZoneId on older MyBatis versions; custom value classes without registering a TypeHandler; dialects returning odd JDBC type codes (e.g. Oracle TIMESTAMP_WITH_LOCAL_TZ) unknown to the registry; enums stored as custom DB types.

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/ace208575684b05e. Report an issue: GitHub.