不灭的火

革命尚未成功,同志仍须努力下载JDK17

作者:AlbertWen  添加时间:2025-04-11 16:36:25  修改时间:2025-04-26 16:37:49  分类:02.MyBatis-Flex  编辑

在 MyBatis-Flex 中处理 PostgreSQL 的数组类型字段(如 int[]varchar[]),需通过自定义 TypeHandler 实现类型转换。以下是具体实现方案及注意事项:

一、核心问题与解决方案

MyBatis-Flex 未原生支持 PostgreSQL 数组类型,但可通过以下方式解决:

1.自定义 TypeHandler

继承 BaseTypeHandler,将 Java 集合(如 List<String>)与 PostgreSQL 的 ARRAY 类型互相转换。

示例代码

package com.fuyo.framework_api.postgresql;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.*;
import java.util.Arrays;
import java.util.List;

@Slf4j
public class ArrayTypeHandler extends BaseTypeHandler<List<String>> {

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType)
        throws SQLException {
        Object[] objects = parameter.toArray();
        Array array = ps.getConnection().createArrayOf("varchar", objects);
        ps.setArray(i, array);
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return getArray(rs.getArray(columnName));
    }

    @Override
    public List<String> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return getArray(rs.getArray(columnIndex));
    }

    @Override
    public List<String> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return getArray(cs.getArray(columnIndex));
    }

    private List<String> getArray(Array array) {
        if (array == null) {
            return null;
        }

        try {
            String[] objects = (String[]) array.getArray();
            return Arrays.asList(objects);
        } catch (SQLException e) {
            log.error("sql转换失败");
        }
        return null;
    }
}

配置实体类

public class User {
    @Column(jdbcType = JdbcType.ARRAY,typeHandler = ArrayTypeHandler.class)
    private List<String> tags;
}

2.SQL 操作符适配

使用 PostgreSQL 数组函数(如 @>ANY)进行查询:

-- 查询包含特定值的数组字段
SELECT * FROM table WHERE array_field @> ARRAY['value'];
-- 关联查询示例
SELECT * FROM table 
LEFT JOIN related_table ON related_table.id = ANY(array_field);

二、高级场景处理

1.动态 SQL 拼接

在 MyBatis-Flex 的 XML 中动态处理数组参数:

<select id="selectByArray" parameterType="map">
    SELECT * FROM table 
    WHERE array_field @> #{arrayParam, typeHandler=org.apache.ibatis.type postgreSQLArrayHandler}
</select>

2.存储过程调用

调用含数组参数的存储过程时,需配置 statementType="CALLABLE" 并指定 TypeHandler

<select id="callproc" statementType="CALLABLE" resultType="void">
    {call func_arr_update(#{ids, typeHandler= ArrayTypeHandler})}
</select>

三、注意事项

  1. 类型一致性
    PostgreSQL 数组类型需与 Java 类型严格匹配(如 int[] 对应 Integer[]),否则可能抛出 TypeException
  2. 性能优化
    避免在复杂查询中频繁使用数组操作符,可结合 array_agg 函数优化聚合查询。
  3. 版本兼容性
    确保 MyBatis-Flex 版本(如 3.5.3+)兼容 PostgreSQL 驱动(如 postgresql-42.x.x.jar)。

四、总结

通过自定义 TypeHandler 和 SQL 操作符适配,MyBatis-Flex 可实现对 PostgreSQL 数组字段的完整支持。开发者需注意类型映射、动态 SQL 拼接及版本兼容性问题。若需进一步优化,可参考 PostgreSQL 的 array_agg 函数或调整存储过程调用逻辑。

 

 

参考:

  1. pgsql中处理数组类型字段