{"record":{"id":"cd7fcca7eb96f78f","repo":"mybatis/mybatis-3","slug":"arraytype-handler-requires-sql-array-or-java-array","errorCode":null,"errorMessage":"ArrayType Handler requires SQL array or java array parameter and does not support type \" + parameter.getClass()","messagePattern":"ArrayType Handler requires SQL array or java array parameter and does not support type \" \\+ parameter\\.getClass\\(\\)","errorType":"exception","errorClass":"TypeException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/type/ArrayTypeHandler.java","lineNumber":86,"sourceCode":"    STANDARD_MAPPING.put(Short.class, JdbcType.SMALLINT.name());\n    STANDARD_MAPPING.put(String.class, JdbcType.VARCHAR.name());\n    STANDARD_MAPPING.put(Time.class, JdbcType.TIME.name());\n    STANDARD_MAPPING.put(Timestamp.class, JdbcType.TIMESTAMP.name());\n    STANDARD_MAPPING.put(URL.class, JdbcType.DATALINK.name());\n  }\n\n  public ArrayTypeHandler() {\n  }\n\n  @Override\n  public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType)\n      throws SQLException {\n    if (parameter instanceof Array) {\n      // it's the user's responsibility to properly free() the Array instance\n      ps.setArray(i, (Array) parameter);\n    } else {\n      if (!parameter.getClass().isArray()) {\n        throw new TypeException(\n            \"ArrayType Handler requires SQL array or java array parameter and does not support type \"\n                + parameter.getClass());\n      }\n      Class<?> componentType = parameter.getClass().getComponentType();\n      String arrayTypeName = resolveTypeName(componentType);\n      Array array = ps.getConnection().createArrayOf(arrayTypeName, (Object[]) parameter);\n      ps.setArray(i, array);\n      array.free();\n    }\n  }\n\n  protected String resolveTypeName(Class<?> type) {\n    return STANDARD_MAPPING.getOrDefault(type, JdbcType.JAVA_OBJECT.name());\n  }\n\n  @Override\n  public Object getNullableResult(ResultSet rs, String columnName) throws SQLException {\n    return extractArray(rs.getArray(columnName));","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/type/ArrayTypeHandler.java#L68-L104","documentation":"ArrayTypeHandler.setNonNullParameter only accepts java.sql.Array instances or genuine Java arrays (Object whose Class.isArray() is true). Any other object (List, String, POJO) reaches the else-branch and triggers this TypeException because MyBatis has no way to convert an arbitrary object into an SQL array via Connection.createArrayOf.","triggerScenarios":"A mapper parameter bound to ArrayTypeHandler (explicitly via #{ids,typeHandler=org.apache.ibatis.type.ArrayTypeHandler} or through javaType resolution) receives a java.util.List, Set, String, or custom object instead of Integer[]/String[]/java.sql.Array.","commonSituations":"Using PostgreSQL/HSQDB array columns and passing a List<Integer> from service code; registering ArrayTypeHandler as the default handler for a too-broad java type; wrapping the array in a DTO so the handler receives the wrapper object.","solutions":["Pass a plain Java array (e.g. Integer[] or String[]) instead of a collection: convert with ids.toArray(new Integer[0])","Or pass a java.sql.Array built via connection.createArrayOf(...) and free() it afterwards","If you must accept List, write a custom TypeHandler extending BaseTypeHandler<List<T>> that delegates to createArrayOf"],"exampleFix":"// before\nList<Integer> ids = ...;\nsqlSession.selectOne(\"stmt\", ids); // ArrayTypeHandler gets a List\n\n// after\nInteger[] ids = list.toArray(new Integer[0]);\nsqlSession.selectOne(\"stmt\", ids);","handlingStrategy":"validation","validationCode":"Object param = /* value bound for the array column */;\nif (!(param instanceof java.sql.Array) && (param == null || !param.getClass().isArray())) {\n  throw new IllegalArgumentException(\"Array parameter required, got: \" + (param == null ? \"null\" : param.getClass()));\n}","typeGuard":"static boolean isSqlArrayParam(Object v) {\n  return v instanceof java.sql.Array || (v != null && v.getClass().isArray());\n}","tryCatchPattern":"try { ... } catch (TypeException e) { // log param class, convert collections to arrays and retry once }","preventionTips":["Type DAO method parameters as arrays (Integer[]), not List, when they map to array columns","Centralize list-to-array conversion at the DAO boundary","Write a unit test asserting the bound parameter class for every array-mapped statement"],"tags":["mybatis","jdbc","array","type-handler","postgresql"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}