Java Mybatis 接收postgreSQL中array_agg的结果

news/2024/7/9 19:31:25 标签: mybatis, java, postgresql

问题描述

因为项目中业务需求,postgreSQL使用了group by与array_agg将varchar或者bigint类型变为一个数组,这样多行结果就变为了一行结果,但是mybatis的jdbcType没有对应的数据类型。如果用string类型去接收,还得用java代码处理成数组,返回给前端有点麻烦。

array_agg介绍

array_agg函数 和string_agg 函数类似,最主要的区别为返回的类型为数组,数组数据类型同输入数据类型一致,array_agg函数支持两种语法。

解决

方式一:

通过设置mybatis xml配置和创建自定义数据类型处理类解决。

教程

maper类 以mybatis-plus常规分页写法示例

java">java">
import java.util.List;

import com.baomidou.mybatisplus.core.metadata.IPage;
import org.springblade.standardmodel.mineupdown.dto.AdvancedDetectionTunnelDTO;
import org.springblade.standardmodel.mineupdown.entity.AdvancedDetection;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface AdvancedDetectionMapper extends BaseMapper<AdvancedDetection> {

    List<AdvancedDetectionTunnelDTO> tunnelPage(IPage page, String tunnelName);

}

mapper.xml文件中设置typeHander

    <resultMap id="BaseResultMap" type="org.springblade.standardmodel.mineupdown.dto.AdvancedDetectionTunnelDTO">
        <result column="ids" jdbcType="ARRAY" property="ids" typeHandler="org.springblade.standardmodel.common.handler.ArrayTypeHandler"/>
    </resultMap>

    <select id="tunnelPage" resultMap="BaseResultMap">
            SELECT
            ids,
            tunnel_id,
            tunnel_name,
            anomalous_region_num
            FROM
            (
            SELECT
            "array_agg" ( ID ) ids,
            tunnel_id,
            tunnel_name,
            "sum" ( anomalous_region_num ) anomalous_region_num
            FROM
            (
            SELECT
            ad.ID,
            ad.tunnel_id,
            tb.hd_hdmc AS tunnel_name,
            ( SELECT COUNT ( 1 ) FROM gis_standard_abnormal_area aa WHERE aa.detection_id = ad.ID ) AS anomalous_region_num
            FROM
            gis_standard_advanced_detection ad
            LEFT JOIN gis_standard_tunnel_base tb ON ad.tunnel_id = tb.ID
            ) T
            GROUP BY
            T.tunnel_id,
            T.tunnel_name
            ) r
         <where>
             <if test="tunnelName!=null">
                 and r.tunnel_name like CONCAT('%',#{tunnelName},'%')
             </if>
         </where>
    </select>

自定义数组类型处理类 ArrayTypeHandler

java">java">

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

import java.sql.*;

public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {

    private static final String TYPE_NAME_VARCHAR = "varchar";
    private static final String TYPE_NAME_INTEGER = "integer";
    private static final String TYPE_NAME_BOOLEAN = "boolean";
    private static final String TYPE_NAME_NUMERIC = "numeric";

    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, Object[] parameter, JdbcType jdbcType) throws SQLException {
        String typeName = null;
        if (parameter instanceof Integer[]) {
            typeName = TYPE_NAME_INTEGER;
        } else if (parameter instanceof String[]) {
            typeName = TYPE_NAME_VARCHAR;
        } else if (parameter instanceof Boolean[]) {
            typeName = TYPE_NAME_BOOLEAN;
        } else if (parameter instanceof Double[]) {
            typeName = TYPE_NAME_NUMERIC;
        }

        if (typeName == null) {
            throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
        }

        Connection conn = ps.getConnection();
        Array array = conn.createArrayOf(typeName, parameter);
        ps.setArray(i, array);
    }

    @Override
    public Object[] getNullableResult(ResultSet resultSet, String s) throws SQLException {
        return getArray(resultSet.getArray(s));
    }

    @Override
    public Object[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
        return getArray(resultSet.getArray(i));
    }

    @Override
    public Object[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        return getArray(callableStatement.getArray(i));
    }

    private Object[] getArray(Array array) {
        if (array == null) {
            return null;
        }
        try {
            return (Object[]) array.getArray();
        } catch (Exception e) {
        }
        return null;
    }

实体类返回对象AdvancedDetectionTunnelDTO

java">java">import io.swagger.annotations.ApiModelProperty;
import lombok.Data;


/**
 * @author TARZAN
 */
@Data
public class AdvancedDetectionTunnelDTO {


    @ApiModelProperty("巷道名称")
    private  String tunnelName;

    @ApiModelProperty("异常区域数")
    private  Integer anomalousRegionNum;

    @ApiModelProperty("超前探id集合")
    private Long[] ids;

}

方式二:

通过 mybatis-plus @TableField(typeHandler = ArrayTypeHandler.class) 注解

实体类返回对象AdvancedDetectionTunnelDTO

java">java">
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.ibatis.type.ArrayTypeHandler;



/**
 * @author TARZAN
 */
@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class AdvancedDetectionTunnelDTO {


    @ApiModelProperty("巷道名称")
    private  String tunnelName;

    @ApiModelProperty("异常区域数")
    private  Integer anomalousRegionNum;

    @ApiModelProperty("超前探id集合")
    @TableField(typeHandler = ArrayTypeHandler.class)
    private Long[] ids;

}

注意事项:

需要用到两个注解才能生效

  1. @TableName(autoResultMap = true)

  1. @TableField(typeHandler = ArrayTypeHandler.class)


http://www.niftyadmin.cn/n/115099.html

相关文章

关于flex盒子padding-right/margin-right不生效

错误代码实例&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"width…

Elasticsearch索引生命周期管理

在ELK架构中&#xff0c;使用Elasticsearch来存储系统日志时&#xff0c;有如下典型的特点&#xff1a; 数据量非常大经常访问新增的数据&#xff0c;随着时间的推移&#xff0c;数据的价值也在逐渐降低 随着数据量的增大&#xff0c;Elasticsearch创建索引的数量也在不断增长…

Mel Spectrogram

参考链接&#xff1a; Short-time Fourier transform - MATLAB stft- MathWorks 中国 https://medium.com/analytics-vidhya/understanding-the-mel-spectrogram-fca2afa2ce53 a spectrogram as a bunch of FFTs stacked on top of each other. 给出hop length后&#xff0…

JavaWeb--用户注册登录案例

用户注册登录案例1 用户登录1.1 需求分析1.2 环境准备1.3 代码实现2 用户注册2.1 需求分析2.2 代码编写3 SqlSessionFactory工具类抽取目标&#xff1a; 能够完成用户登录注册案例的实现能够完成SqlSessionFactory工具类的抽取 接下来我们通过两个比较常见的案例&#xff0c;一…

ccc-pytorch-小实验合集(4)

文章目录一、 Himmelblau 优化二、多分类实战-Mnist三、Sequential与CPU加速-Mnist四、visidom可视化一、 Himmelblau 优化 Himmelblau 是一个具有4个最优值的2维目标函数。其函数和最优值点如下&#xff1a; 图象绘制&#xff1a; import numpy as np from matplotlib impo…

bat实战总结

基础版本以一个情景的方式来描述bat的实战情况&#xff1a;需求情景1. 启动命令时&#xff0c;一个cmd里启动好几个服务的情况下&#xff0c;前后启动互不影响&#xff0c;且独立窗口&#xff0c;不会影响到彼此的日志,同时&#xff0c;调用关闭命令会关闭各个服务对应的窗口&a…

分布式锁详解

文章目录分布式锁是什么基于 Redis 实现分布式锁如何基于Redis实现一个简单的分布式锁为什么要给锁设置一个过期时间&#xff1f;如何实现锁的优雅续期&#xff1f;如何实现可重入锁&#xff1f;Redis 如何解决集群情况下分布式锁的可靠性&#xff1f;分布式锁是什么 java单机…

Qt开发基本步骤示例:输入半径显示圆的面积

目录 1. 创建一个新项目 1.1 创建类的基类 1.2 main.cpp代码释义 2. 代码写在哪&#xff1f; 2.1 怎么找到我们需要的函数&#xff1f; 1. 创建一个新项目 点击创建项目&#xff0c;开始创建&#xff1a; 1.1 创建类的基类 QMainWindow&#xff1a;带菜单栏的窗口QWidge…