mybatis类型转换器处理PostGis数据库geometry类型转换

在入库和查询中需要自动的让geometry的类型和实体类中的类型映射。

实体类中接收参数是String类型(geoJson)

PostGis中的geometry类型是十六进制的扩展WKB类型(EWKB),

虽然Postgis数据库中提供类类型转换函数,能转换各种类型postgis常用命令_yaoct的博客-CSDN博客

但是基于mybatis框架查询时,就需要用java代码来转换。初步方案时mybatis中的类型转换器。

先引入java处理GIS的库,这里用的是Geotools库。

1.java代码中数据类型的转换

geotools的maven引入:


    
        27.0
    
    
        
            osgeo
            OSGeo Release Repository
            https://repo.osgeo.org/repository/release/
            
                false
            
            
                true
            
        
    
    
        
        
            org.geotools
            gt-geojson
            ${geotools.version}
        
        
            org.geotools
            gt-main
            ${geotools.version}
        
        
            org.geotools
            gt-opengis
            ${geotools.version}
        
        
            org.geotools
            gt-referencing
            ${geotools.version}
        
        
            org.geotools
            gt-metadata
            ${geotools.version}
        
        
            org.geotools
            gt-epsg-hsql
            ${geotools.version}
        
    

Geotools工具类转换WKB和Geojson

WKBReader reader = new WKBReader( );
        Geometry geometry = reader.read(WKBReader.hexToBytes("0101000020E61000002C39382229FD5D4085716007088C3E40"));
        // 设置保留6位小数,否则GeometryJSON默认保留4位小数
        GeometryJSON geometryJson = new GeometryJSON(7);
        String s = geometryJson.toString(geometry);
        System.out.println(s);

        //{"type":"Point","coordinates":[119.9556356,30.5469975]}
        //EWKB->转geojson丢失信息
        Geometry read = geometryJson.read("{\"type\":\"Point\",\"coordinates\":[119.9556356,30.5469975]}");
        System.out.println(read.toString());
        WKBWriter wkbWriter = new WKBWriter();
        byte[] write = wkbWriter.write(geometry);
        String s1 = WKBWriter.toHex(write);
        System.out.println(s1);

2.mybatis-plus类型转换器

这里框架用的是mybatis-plus,所有使用转换时,mybatis-plus中的实体类也要配置一些转换注解,其他和mybaitis中的xml配置属性相同。参考

MyBatis Plus 自动类型转换之TypeHandler


@Data
@ToString
@TableName (value = "test_table",autoResultMap = true)
@ApiModel ("test")
public class TestTable  implements Serializable {

	private static final long serialVersionUID =  8881418345724766899L;

	@TableId(value = "id")
	private Integer id;

	@ApiModelProperty(value = "二进制WKB数据")
   	@TableField(value = "position",typeHandler = WKB2GeoJsonTypeHandler.class)
    @JsonRawValue
	private String position;

   	@TableField("name")
	private String name;

}

mybatis-plus配置添加转换器包路径,类似mybatis,之后用于写xml中sql

mybatis-plus:
  type-handlers-package: com.zjzy.mapper.typehandler
  configuration:
    map-underscore-to-camel-case: true
    auto-mapping-behavior: full
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath*:mapper/**/*Mapper.xml

3.mybatis类型转换器转换geometry格式

 因为缺少JDBC映射,数据库开始报错:‘类型为 geometry, 但表达式的类型为 character varying’

参考:Mybatis-plus读取和保存Postgis geometry数据 - 简书 

应该是缺少JDBC-type类型。引入响应的postGIS驱动

添加maven包:

        
        
            net.postgis
            postgis-jdbc
            2.5.0
        

类型转换器代码:

package com.zjzy.mapper.typehandler;

import com.zjzy.mapper.CommonCodeMapper;
import com.zjzy.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.WKBReader;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ParseException;
import org.postgis.PGgeometry;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Set;

/**
 * @version 2.0
 * @description
 * @Author yaoct
 * @create 2021/12/22 16:19
 */
@Slf4j
public class WKB2GeoJsonTypeHandler implements TypeHandler {

    /**
     * 插入数据,转换,geoJson2EWKB
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
//EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
//        CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
//        String EWKB = mapper.geo2EWKB(parameter);
//        PGgeometry ewkb = new PGgeometry(EWKB);
//        ps.setObject(i,ewkb);
        
        //通过geoTool转换WKB
        GeometryJSON geometryJson = new GeometryJSON(7);
        Geometry read = null;
        try {
            read = geometryJson.read(parameter);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        System.out.println(read.toString());
        read.setSRID(4326);
//        GeometryJSON geometryJson = new GeometryJSON(7);
        WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
        byte[] write = wkbWriter.write(read);
        String s1 = WKBWriter.toHex(write);
        PGgeometry ewkb = new PGgeometry(s1);
        ps.setObject(i,ewkb);
    }

    /**
     * 取出数据转换,WKB->Geojson
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        String WKB = rs.getString(columnName);
        if(WKB==null){
            return null;
        }
        WKBReader reader = new WKBReader( );
        Geometry geometry = null;
        try {
            geometry = reader.read(WKBReader.hexToBytes(WKB));
        } catch (ParseException e) {
            //转换失败
            return null;
        }
        //转换成4326
        try {
            int srid = geometry.getSRID();
            CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
            CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326",true);
            MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
            geometry = JTS.transform(geometry, transform);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 设置保留6位小数,否则GeometryJSON默认保留4位小数
        GeometryJSON geometryJson = new GeometryJSON(7);
        return geometryJson.toString(geometry);
    }

    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }
}
@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    //通过name获取 Bean.
    public static Object getBean(String name) {
        return getApplicationContext().getBean(name);
    }

    //通过class获取Bean.
    public static  T getBean(Class clazz) {
        return getApplicationContext().getBean(clazz);
    }

    //通过name,以及Clazz返回指定的Bean
    public static  T getBean(String name, Class clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

    //关闭springboot
    public static void close(){
        ((ConfigurableApplicationContext)(getApplicationContext())).close();
    }

    //得到当前线程的HttpServletResponse,可在静态方法中得到
    public static HttpServletResponse getHttpServletResponse(){
        return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
    }

    //得到当前线程的HttpServletRequest,可在静态方法中得到
    public static HttpServletRequest getHttpServletRequest(){
        return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
    }

}

@Repository
public interface CommonCodeMapper extends BaseMapper {

    /**
     * EWKB是pg数据库自定义的类型,所以需要用数据库函数
     * @param geoJson
     * @return
     */
    @Select("select ST_GeomFromGeoJSON(#{geoJson})")
    String geo2EWKB(String geoJson);


}

=============================mybatis中使用================================ 

在mapper类中使用示例:https://www.jianshu.com/p/6465189984b0

/**
 * 使用ResultMap 
 */
@Results(id = "userMap", value = {
            //可以使用这种方式来处理字段名和数据库表字段名不一致的情况
            @Result(column = "username", property = "username", jdbcType=JdbcType.VARCHAR,typeHandler = WKB2GeoJsonTypeHandler.class),
            @Result(column = "passwd", property = "passwd", jdbcType=JdbcType.VARCHAR),
            @Result(column = "birth_day", property = "birthDay", jdbcType=JdbcType.VARCHAR)
    })
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMap(Long id);

/**
 * 引用其他的Result 
 */
@ResultMap("userMap")
@Select("SELECT * FROM t_user WHERE id=#{id}")
User loadByIdResultMapReference(Long id);

在xml中使用示例示例:

    
        
    

    

注意:

1.postgresql的JDBC实现中(驱动),数据自定义的类型对应java类型一般都通过实现

org.postgresql.util.PGobject。

2.对应数据库geometry类型的java类不在PG的JDBC驱动的实现类中,因为geometry类型在PG的扩展postgis中,所以响应的要引入postGIS这部分的驱动,mybatis类型转换器处理PostGis数据库geometry类型转换_第1张图片

3. PG的JDBC驱动底层也是通过SOCKET连接org.postgresql.core.PGStream#createSocket

4.原生jdbc接口在java.sql包中。

5.一定要实现org.postgresql.util.PGobject#getValue方法因为,org.postgresql.jdbc.PgPreparedStatement#setPGobject底层调用org.postgresql.jdbc.PgPreparedStatement#setString(int, java.lang.String, int)时

要用到org.postgresql.util.PGobject#getValue方法

mybatis类型转换器处理PostGis数据库geometry类型转换_第2张图片

 mybatis类型转换器处理PostGis数据库geometry类型转换_第3张图片

==============================2022.12.12===========================

以下方式不用导入 net.postgis包

package com.zjzy.mapper.typehandler;

import com.alibaba.fastjson.JSONObject;
import com.zjzy.util.GisUtil;
import com.zjzy.util.SpringContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.WKBReader;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ByteOrderValues;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBWriter;
import org.locationtech.jts.io.WKTWriter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.postgis.PGbox2d;
import org.postgis.PGgeometry;
import org.postgresql.util.PGobject;
import org.springframework.core.env.Environment;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * @version 1.0
 * @description
 * @Author yaoct
 * @create 2021/12/22 16:19
 */
@Slf4j
public class WKB2GeoJsonTypeHandler implements TypeHandler {

    /**
     * 插入数据,转换,geoJson2EWKB
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        //EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
//        CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
//        String EWKB = mapper.geo2EWKB(parameter);
//        PGgeometry ewkb = new PGgeometry(EWKB);
//        ps.setObject(i,ewkb);

        //通过geoTool转换WKB
        GeometryJSON geometryJson = new GeometryJSON(7);
        Geometry geometry = null;
        try {
            geometry = geometryJson.read(parameter);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        System.out.println(read.toString());
        geometry.setSRID(4326);
//        GeometryJSON geometryJson = new GeometryJSON(7);

        //方式1.基于net.postgis
//        WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
//        byte[] write = wkbWriter.write(geometry);
//        String s1 = WKBWriter.toHex(write);
//        PGgeometry ewkb = new PGgeometry(s1);//EWKB比WKB多了SRID头字符串,PGgeometry.toString()会自动添加SRID
//        ps.setObject(i,ewkb);

        //方式2.设置ewkb,Postgresql驱动会先去数据库 pg_catalog.pg_type 查出geometry的类型id,这里的geometry字符串对应数据库pg_catalog.pg_type表中的geometry
        //以下方式不用导入net.postgis包
//        PGobject pGobject = new PGobject();
//        pGobject.setType("geometry");
//        pGobject.setValue(s1);
//        ps.setObject(i,pGobject);

        //方式3.设置拼接ewkt
        //以下方式不用导入net.postgis包,ewkb太长会超出sql限制,以下转换为ewkt
        PGobject pGobject = new PGobject();
        pGobject.setType("geometry");
        String pre="SRID="+4326+";";
        pGobject.setValue(pre+GisUtil.Geometry2WKT(geometry));
        ps.setObject(i,pGobject);
    }


    /**
     * 取出数据转换,WKB->Geojson
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public String getResult(ResultSet rs, String columnName) throws SQLException {
        String WKB = rs.getString(columnName);
        if(WKB==null){
            return null;
        }
        WKBReader reader = new WKBReader( );
        Geometry geometry = null;
        try {
            geometry = reader.read(WKBReader.hexToBytes(WKB));
        } catch (ParseException e) {
            //转换失败
            return null;
        }
        //转换成4326
        try {
            int srid = geometry.getSRID();
            if(srid==0)srid=4549;//默认4549
            int targetSrid=4326;//默认4326
            Environment environment = SpringContextUtil.getBean(Environment.class);
            if(environment!=null){
                String sridTarget = environment.getProperty("sridTarget");
                if(sridTarget!=null){
                    try {
                        targetSrid=Integer.valueOf(sridTarget);
                    } catch (Exception e){
                        //转换失败
                    }
                }
            }

            CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
            CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:"+targetSrid,true);
            MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
            geometry = JTS.transform(geometry, transform);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 设置保留6位小数,否则GeometryJSON默认保留4位小数
        GeometryJSON geometryJson = new GeometryJSON(7);
        String json = geometryJson.toString(geometry);
        JSONObject jsonObject = JSONObject.parseObject(json);
        jsonObject.put("srid",geometry.getSRID());
        return jsonObject.toJSONString();
    }

    @Override
    public String getResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }

}
package com.zjzy.util;

import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.WKBReader;
import org.geotools.referencing.CRS;
import org.geotools.referencing.GeodeticCalculator;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.*;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

import java.io.IOException;

/**
 * @Author yaoct
 * @Date 2022/9/16 10:55
 * @Version 1.0
 * @description
 */
public class GisUtil {

    /**
     * WKB字符串转Geometry格式
     * @param WKB
     * @return
     */
    public static Geometry WKB2Geometry(String WKB){
        WKBReader reader = new WKBReader();
        Geometry geometry = null;
        try {
            geometry = reader.read(WKBReader.hexToBytes(WKB));
        } catch (ParseException e) {
            //转换失败
            throw new RuntimeException("转换失败",e);
        }
        return geometry;
    }

    /**
     * Geometry格式转WKB字符串
     * @param geometry
     * @return
     */
    public static String Geometry2WKB(Geometry geometry){
        WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
        byte[] write = wkbWriter.write(geometry);
        String ret = WKBWriter.toHex(write);
        return ret;
    }

    /**
     * WKT字符串转Geometry格式
     * @param WKT
     * @return
     */
    public static Geometry WKT2Geometry(String WKT){
        WKTReader reader = new WKTReader();
        Geometry geometry = null;
        try {
            geometry = reader.read(WKT);
        } catch (ParseException e) {
            //转换失败
            throw new RuntimeException("转换失败",e);
        }
        return geometry;
    }

    /**
     * Geometry格式转WKT字符串
     * @param geometry
     * @return
     */
    public static String Geometry2WKT(Geometry geometry){
        WKTWriter wktWriter = new WKTWriter();
        String wkt= wktWriter.write(geometry);
        return wkt;
    }

    /**
     * 转换Geometry坐标
     * @param geometry
     * @param targetSrid 新坐标
     * @return
     */
    public static Geometry coordinateTransfer(Geometry geometry, int targetSrid){
        int originSrid = geometry.getSRID();
        CoordinateReferenceSystem sourceCRS = null;
        CoordinateReferenceSystem targetCRS = null;
        MathTransform transform=null;
        try {
            sourceCRS = CRS.decode("EPSG:"+originSrid,true);
            targetCRS = CRS.decode("EPSG:"+targetSrid,true);
            transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
        } catch (FactoryException e) {
            throw new RuntimeException("坐标错误",e);
        }
        Geometry ret = null;
        try {
            ret = JTS.transform(geometry, transform);
        } catch (TransformException e) {
            throw new RuntimeException("坐标转换错误",e);
        }
        return ret;
    }

    /**
     * Geometry->geoJson
     * @param geometry
     * @return
     */
    public static String geometry2GeoJson(Geometry geometry){
        // 设置保留6位小数,否则GeometryJSON默认保留4位小数
        GeometryJSON geometryJson = new GeometryJSON(7);
        String json = geometryJson.toString(geometry);
//        JSONObject jsonObject = JSONObject.parseObject(json);
//        jsonObject.put("srid",geometry.getSRID());
//        return jsonObject.toJSONString();
        return json;
    }

    /**
     * geoJson->Geometry
     * @param geoJson
     * @return
     */
    public static Geometry geoJson2Geometry(String geoJson){
        GeometryJSON geometryJson = new GeometryJSON(7);
        Geometry ret=null;
        try {
            Geometry read = geometryJson.read(geoJson);
        } catch (IOException e) {
            throw new RuntimeException("转换失败",e);
        }
        return ret;
    }

    /**
     * 计算两点间的距离
     * @param lon1
     * @param lat1
     * @param lon2
     * @param lat2
     * @return
     */
    public static double calculateDistance(double lon1,double lat1,double lon2,double lat2){
        //CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
        GeodeticCalculator geodeticCalculator = new GeodeticCalculator(DefaultGeographicCRS.WGS84);
        // 起点经纬度
        geodeticCalculator.setStartingGeographicPoint(lon1,lat1);
        // 末点经纬度
        geodeticCalculator.setDestinationGeographicPoint(lon2,lat2);
        // 计算距离,单位:米
        double distance = geodeticCalculator.getOrthodromicDistance();
        return distance;
    }
}

===========================2023.3.8===============================

转换成map类型,实体类接受前端传入json兼容性更好

package com.wisdomcity.laian.monitor.mapper.typehandler;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fhs.common.spring.SpringContextUtil;
import com.kingbase8.util.KBobject;
import com.wisdomcity.laian.monitor.utils.GisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import org.geotools.geojson.geom.GeometryJSON;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.WKBReader;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.io.ByteOrderValues;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBWriter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

/**
 * @version 1.0
 * @description
 * @Author yaoct
 * @create 2021/12/22 16:19
 */
@Slf4j
public class WKB2GeoJsonTypeHandler implements TypeHandler {

    /**
     * 插入数据,转换,geoJson2EWKB
     * @param ps
     * @param i
     * @param parameter
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setParameter(PreparedStatement ps, int i, Map parameter, JdbcType jdbcType) throws SQLException {
        //EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
//        CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
//        String EWKB = mapper.geo2EWKB(parameter);
//        PGgeometry ewkb = new PGgeometry(EWKB);
//        ps.setObject(i,ewkb);

        //通过geoTool转换WKB
        GeometryJSON geometryJson = new GeometryJSON(7);
        Geometry geometry = null;
        try {
            geometry = geometryJson.read(JSONObject.toJSONString(parameter));
        } catch (IOException e) {
            e.printStackTrace();
        }
//        System.out.println(read.toString());
        geometry.setSRID(4326);
//        GeometryJSON geometryJson = new GeometryJSON(7);

        //方式1.基于net.postgis
        WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
        byte[] write = wkbWriter.write(geometry);
        String s1 = WKBWriter.toHex(write);
//        PGgeometry ewkb = new PGgeometry(s1);//EWKB比WKB多了SRID头字符串,PGgeometry.toString()会自动添加SRID
//        ps.setObject(i,ewkb);

        //方式2.设置ewkb,Postgresql驱动会先去数据库 pg_catalog.pg_type 查出geometry的类型id,这里的geometry字符串对应数据库pg_catalog.pg_type表中的geometry
//        以下方式不用导入net.postgis包
//        PGobject pGobject = new PGobject();
//        pGobject.setType("geometry");
//        pGobject.setValue(s1);
//        ps.setObject(i,pGobject);

        //方式3.设置拼接ewkt
        //以下方式不用导入net.postgis包,ewkb太长会超出sql限制,以下转换为ewkt
//        PGobject pGobject = new PGobject();
//        pGobject.setType("geometry");
//        String pre="SRID="+4326+";";
//        pGobject.setValue(pre+GisUtil.Geometry2WKT(geometry));
//        ps.setObject(i,pGobject);
        KBobject pGobject = new KBobject();
        pGobject.setType("geometry");
        String pre="SRID="+4326+";";
        pGobject.setValue(pre+ GisUtil.Geometry2WKT(geometry));
        ps.setObject(i,pGobject);
    }


    /**
     * 取出数据转换,WKB->Geojson
     * @param rs
     * @param columnName
     * @return
     * @throws SQLException
     */
    @Override
    public Map getResult(ResultSet rs, String columnName) throws SQLException {
        String WKB = rs.getString(columnName);
        if(WKB==null){
            return null;
        }
        WKBReader reader = new WKBReader( );
        Geometry geometry = null;
        try {
            geometry = reader.read(WKBReader.hexToBytes(WKB));
        } catch (ParseException e) {
            //转换失败
            return null;
        }
        //转换成4326
        try {
            int srid = geometry.getSRID();
//            if(srid==0)srid=4549;//默认4549
            int targetSrid=4326;//默认4326
//            Environment environment = SpringContextUtil.getBean(Environment.class);
//            if(environment!=null){
//                String sridTarget = environment.getProperty("sridTarget");
//                if(sridTarget!=null){
//                    try {
//                        targetSrid=Integer.valueOf(sridTarget);
//                    } catch (Exception e){
//                        //转换失败
//                    }
//                }
//            }
            if(srid!=targetSrid&&srid!=0){
                CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
                CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:"+targetSrid,true);
                MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
                geometry = JTS.transform(geometry, transform);
                geometry.setSRID(targetSrid);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 设置保留6位小数,否则GeometryJSON默认保留4位小数
        GeometryJSON geometryJson = new GeometryJSON(7);
        String json = geometryJson.toString(geometry);
//        JSONObject jsonObject = JSONObject.parseObject(json);
//        jsonObject.put("srid",geometry.getSRID());
//        return jsonObject.toJSONString();
        return JSONObject.parseObject(json);
    }

    @Override
    public Map getResult(ResultSet rs, int columnIndex) throws SQLException {
        return null;
    }

    @Override
    public Map getResult(CallableStatement cs, int columnIndex) throws SQLException {
        return null;
    }

}

实体类字段改为 :

	@ApiModelProperty(value = "二进制WKB数据")
	@TableField(value = "location",typeHandler = WKB2GeoJsonTypeHandler.class)
	private Map location;

xml中使用


        
    

===================================================================

参考:

Mybatis-plus读取和保存Postgis geometry数据 - 简书

MyBatis Plus 自动类型转换之TypeHandler - 周世元ISO8859-1 - 博客园

GeoTools The Open Source Java GIS Toolkit — GeoTools

Geotools中Geometry对象与GeoJson的相互转换_mathyrs的博客-CSDN博客_geojson转geometry

mybatis 自定义TypeHandler映射Geometry空间几何数据 PGPoint (java +mybatis+ pgsql) - 灰信网(软件开发博客聚合)

Mybatis常用注解

你可能感兴趣的:(GIS,mybatis,postgresql,数据库,database)