如何使用mybatis向postgreSQL插入一个数组值
How to insert an array value to postgreSQL with mybatis
我的class
class PgFolder {
long id;
int[] pgFeature;
}
getter...
setter...
我的table
CREATE TABLE folder {
ID BIGSERIAL PRIMARY KEY,
feature INT[]
}
我的xml
<insert id="insertManyFolder" parameterType="java.util.List">
INSERT INTO
folder
(feature)
VALUES
<foreach collection="list" item="item" index="" separator=",">
(#{item.pgFeature})
</foreach>
</insert>
我想插入一个 List<PgFolder>
列表。列表中有很多 PgFolder 实例。当我运行这个程序时,我得到一个错误:
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.**
为什么我收到这条错误消息?如何以正确的方式插入数组值?
如果我在 postgres 客户端中使用 sql,我可以插入一个数组值。所以我安装的版本的postgres可以支持数组值。
我将解释两种解决方案,即映射 Integer[]
属性 和映射 int[]
属性.
映射Integer[]
class PgFolder {
long id;
Integer[] pgFeature;
// getter / setter
}
这种情况下,可以使用MyBatis的built-in ArrayTypeHandler
.
在参数引用中指定 typeHandler
就足够了。
<foreach ...>
(#{item.pgFeature,typeHandler=org.apache.ibatis.type.ArrayTypeHandler})
</foreach>
映射int[]
由于 built-in ArrayTypeHandler
可能不适用于原始数组,您可能必须编写自定义类型处理程序。例如
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;
}
}
然后在参数引用中指定类型处理程序。
<foreach ...>
(#{item.pgFeature,typeHandler=pkg.PgIntArrayTypeHandler})
</foreach>
使用 MyBatis 3.5.5 和 pgjdbc 42.2.15 测试。
我的class
class PgFolder {
long id;
int[] pgFeature;
}
getter...
setter...
我的table
CREATE TABLE folder {
ID BIGSERIAL PRIMARY KEY,
feature INT[]
}
我的xml
<insert id="insertManyFolder" parameterType="java.util.List">
INSERT INTO
folder
(feature)
VALUES
<foreach collection="list" item="item" index="" separator=",">
(#{item.pgFeature})
</foreach>
</insert>
我想插入一个 List<PgFolder>
列表。列表中有很多 PgFolder 实例。当我运行这个程序时,我得到一个错误:
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.**
为什么我收到这条错误消息?如何以正确的方式插入数组值? 如果我在 postgres 客户端中使用 sql,我可以插入一个数组值。所以我安装的版本的postgres可以支持数组值。
我将解释两种解决方案,即映射 Integer[]
属性 和映射 int[]
属性.
映射Integer[]
class PgFolder {
long id;
Integer[] pgFeature;
// getter / setter
}
这种情况下,可以使用MyBatis的built-in ArrayTypeHandler
.
在参数引用中指定 typeHandler
就足够了。
<foreach ...>
(#{item.pgFeature,typeHandler=org.apache.ibatis.type.ArrayTypeHandler})
</foreach>
映射int[]
由于 built-in ArrayTypeHandler
可能不适用于原始数组,您可能必须编写自定义类型处理程序。例如
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;
}
}
然后在参数引用中指定类型处理程序。
<foreach ...>
(#{item.pgFeature,typeHandler=pkg.PgIntArrayTypeHandler})
</foreach>
使用 MyBatis 3.5.5 和 pgjdbc 42.2.15 测试。