KingBaseDB对POINT类型和PATH类型的应用

前言

由于业务需要对坐标信息进行存储,包括中心点和区域坐标数组,然后就开始考虑数据的存储问题,刚开始想着用最简单的两个字段分别存储经度纬度,这样发现关联查询表可能会比较多,有点麻烦。之后想起来kingbase好像有对坐标信息支持的类型,于是查了查文档,试了一下就有了这篇文章,这篇文章主要目的在于如何在实际业务中应用POINT数据类型和PATH数据与java对象的映射转换,完成业务功能。

涉及的工具和库

  • KingBaseES V8R3
  • Mybatis-plus
  • lombok

具体步骤

创建数据库表
-- 位置表信息
create table busi_assets_location
(
  id varchar(25) not null
    constraint busi_assets_location_pk
      primary key,
  fid VARCHAR(50) NOT NULL,
  centre POINT,
  area Decimal(10,2),
  boundary path,
  create_time timestamp not null,
  create_by VARCHAR(25) not null,
  update_time timestamp,
  update_by varchar(25)
);


comment on TABLE public.busi_assets_location is '资产地理信息表';
comment on column busi_assets_location.id is '主键';
comment on column busi_assets_location.fid is '资产id';
comment on column busi_assets_location.area is '面积';
comment on column busi_assets_location.boundary is '边界坐标';
comment on column busi_assets_location.create_time is '创建时间';
comment on column busi_assets_location.create_by is '创建人';
comment on column busi_assets_location.update_time is '更新时间';
comment on column busi_assets_location.update_by is '更新人';
创建实体类
package com.seerbigdata.assets.domain.po;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.kingbase8.geometric.KBpath;
import com.kingbase8.geometric.KBpoint;
import com.seerbigdata.common.core.domain.BaseEntity;
import com.seerbigdata.common.handler.KBPathTypeHandler;
import com.seerbigdata.common.handler.KBPointTypeHandler;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;

@Data
@TableName("busi_assets_location")
public class AssertsLocation extends BaseEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * ID
     */
    @TableId(value = "id")
    @ApiModelProperty(value = "id")
    private String id;

    /**
     * 资产id
     */
    private String fid;

    /**
     * 中心点坐标
     */
    @TableField(value = "centre",typeHandler = KBPointTypeHandler.class)
    private KBpoint centre;

    /**
     * 面积
     */
    private BigDecimal area;

    /**
     * 边界坐标
     */
    @TableField(value = "boundary",typeHandler = KBPathTypeHandler.class)
    private KBpath boundary;

}

编写类型处理器(重点)

其实最重要的就是根据kingbase提供的jdbc驱动中的地理位置类型编写相应的类型处理器,然后在跟实体类做关联,让后mybatis-plus能找到对应的处理器来对属性进行赋值就可以了,剩下的CRUD跟平常的开发过程并没有什么区别,这里就不多加详述了,下面直接把两个类型处理器的代码贴出来

package com.seerbigdata.common.handler;

import com.kingbase8.geometric.KBpath;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.sql.*;

@MappedTypes(KBpath.class)
public class KBPathTypeHandler extends BaseTypeHandler<KBpath> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, KBpath parameter, JdbcType jdbcType) throws SQLException {
        // 构造path对象的值
        // KBpath的getValue方法会自动将坐标数据组装成可以存入数据库的字符串,详细的可以自行看源码,很简单
        ps.setObject(i, parameter.getValue(), Types.OTHER); // 使用 Types.OTHER 类型表示 KingBase 中的KBpath 类型
    }


    @Override
    public KBpath getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 从 ResultSet 获取 Kingbase 中 KBpath 类型,并转换为 KBpath 对象
        Object object = rs.getObject(columnName);
        return (KBpath) object;
    }

    @Override
    public KBpath getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 从 ResultSet 获取 Kingbase 中 KBpath 类型,并转换为 KBpath 对象
        Object object = rs.getObject(columnIndex);
        return (KBpath) object;
    }

    @Override
    public KBpath getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 从 CallableStatement 获取 Kingbase 中 KBpath 类型,并转换为 KBpath 对象
        Object object = cs.getObject(columnIndex);
        return (KBpath) object;
    }
}

package com.seerbigdata.common.handler;

import com.kingbase8.geometric.KBpoint;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;

import java.sql.*;

@MappedTypes(KBpoint.class)
public class KBPointTypeHandler extends BaseTypeHandler<KBpoint> {
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, KBpoint parameter, JdbcType jdbcType) throws SQLException {
        // 将 Point 对象转换为 Kingbase 中 POINT 类型
        ps.setObject(i,parameter.getValue(),Types.OTHER);
    }

    @Override
    public KBpoint getNullableResult(ResultSet rs, String columnName) throws SQLException {
        // 从 ResultSet 获取 Kingbase 中 POINT 类型,并转换为 Point 对象
        Object object = rs.getObject(columnName);
        return (KBpoint) object;
    }

    @Override
    public KBpoint getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        // 从 ResultSet 获取 Kingbase 中 POINT 类型,并转换为 Point 对象
        Object object = rs.getObject(columnIndex);
        return (KBpoint) object;
    }

    @Override
    public KBpoint getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        // 从 CallableStatement 获取 Kingbase 中 POINT 类型,并转换为 Point 对象
        Object object = cs.getObject(columnIndex);
        return (KBpoint) object;
    }
}

有了这两个类型处理器,接下来就只需要在CRUD的时候能关联上对应的处理器进行处理就好了。

mapper xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.seerbigdata.assets.mapper.AssertsLocationMapper">

    <resultMap id="assertsLocationMap" type="com.seerbigdata.assets.domain.po.AssertsLocation">
        <id property="id" column="id" />
        <result property="fid" column="fid" />
        <!-- 指定类型处理器 -->
        <result property="centre" column="centre" javaType="com.kingbase8.geometric.KBpoint" jdbcType="OTHER"
                typeHandler="com.seerbigdata.common.handler.KBPointTypeHandler" />
        <result property="area" column="area" />
        <result property="boundary" column="boundary" javaType="com.kingbase8.geometric.KBpath" jdbcType="OTHER"
                typeHandler="com.seerbigdata.common.handler.KBPathTypeHandler" />
        <result property="createTime" column="create_time"/>
        <result property="createBy" column="create_by"/>
        <result property="updateTime" column="update_time"/>
        <result property="updateBy" column="update_by"/>
    </resultMap>

    <select id="listAssertsLocations" resultMap="assertsLocationMap">
        select * from busi_assets_location where fid = #{fid}
    </select>





</mapper>

mapper
package com.seerbigdata.assets.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.seerbigdata.assets.domain.po.AssertsLocation;
import com.seerbigdata.assets.domain.po.Contract;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.util.List;


@Mapper
public interface AssertsLocationMapper extends BaseMapper<AssertsLocation> {


    /**
     * 地理位置信息查询
     * @param fid
     * @return
     */
    List<AssertsLocation> listAssertsLocations(@Param("fid") String fid);
}

后记

经过测试,已经可以正常对数据进行CRUD,接口也能正常返回坐标数据;但是数据的结构仍然是以{x:101.22222,y:33.0000}这种json格式返回给前端与自己定义两个数据库字段的区别不是很大,但在数据库层面可以使用PostgreSQL中的地理位置信息函数,这块有兴趣的话可以看下开发手册。
前端要求要标准的geo格式进行数据返回,例如:[101.22222,33.0000]这种格式,最终为了方便还是采用mongoDB来进行数据存储。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值