简体   繁体   中英

How to insert an array value to postgreSQL with mybatis

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.

I'll explain both solutions ie 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. eg

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM