0

My class

class PgFolder {
    long id;
    int[] pgFeature;
}
getter...
setter...

My table

CREATE TABLE folder {
    ID BIGSERIAL PRIMARY KEY,
    feature INT[]
}

My xml

<insert id="insertManyFolder" parameterType="java.util.List">
    INSERT INTO
        folder
       (feature)
        VALUES
        <foreach collection="list" item="item" index="" separator=",">
            (#{item.pgFeature})
        </foreach>
</insert>

I want to insert a List<PgFolder> list. There are many PgFolder instance in the list. When I run the program, I got an error:

org.apache.ibatis.exceptions.PersistenceException:
Error updating database. Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.pgFeature'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.
Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.pgFeature'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.**

Why I got this error message? How to insert the array value in the right way? I can insert an array value if I use the sql in postgres client. so the postgres of the version I installed can support the array value.

1
  • Is it possible to change the type of pgFeature from int[] to Integer[] ? The solution will be much cleaner if you avoid primitive array. Commented Aug 20, 2020 at 17:15

1 Answer 1

4

I'll explain both solutions i.e. mapping Integer[] property and mapping int[] property.

Mapping Integer[]

class PgFolder {
  long id;
  Integer[] pgFeature;
  // getter / setter
}

In this case, you can use MyBatis' built-in ArrayTypeHandler.
Specifying typeHandler in the parameter reference is sufficient.

<foreach ...>
  (#{item.pgFeature,typeHandler=org.apache.ibatis.type.ArrayTypeHandler})
</foreach>

Mapping int[]

As the built-in ArrayTypeHandler may not work with primitive arrays, you may have to write a custom type handler. e.g.

package pkg;

import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

public class PgIntArrayTypeHandler extends BaseTypeHandler<int[]>{
  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, int[] parameter, JdbcType jdbcType)
      throws SQLException {
    ps.setObject(i, parameter);
  }

  @Override
  public int[] getNullableResult(ResultSet rs, String columnName) throws SQLException {
    return extractArray(rs.getArray(columnName));
  }

  @Override
  public int[] getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    return extractArray(rs.getArray(columnIndex));
  }

  @Override
  public int[] getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
    return extractArray(cs.getArray(columnIndex));
  }

  protected int[] extractArray(Array array) throws SQLException {
    if (array == null) {
      return null;
    }
    // pgjdbc returns Integer[] for the INT[] column
    Integer[] wrapperArray = (Integer[]) array.getArray();
    int[] result = Arrays.stream(wrapperArray).mapToInt(Integer::intValue).toArray();
    array.free();
    return result;
  }
}

Then specify the type handler in the parameter reference.

<foreach ...>
  (#{item.pgFeature,typeHandler=pkg.PgIntArrayTypeHandler})
</foreach>

Tested with MyBatis 3.5.5 and pgjdbc 42.2.15.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. It works. The mybatis 3.4 does not work and throws the exception "cannot cast Ljava.lang.Integer to java.sql.Array". The version 3.5.5 works well.
@S.Lee You are right. In versions older than 3.5.2, the built-in ArrayTypeHandler#setNonNullParameter only supported java.sql.Array. See this issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.