当前位置:   article > 正文

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

mybatis geometry

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

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

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

文档Chapter 4. Data Management

说明输入格式是EWKB二进制格式,或者EWKB和EWKT文本格式。输出格式为二进制EWKB或文本格式HEXEWKB

以下接收到文本格式HEXEWKB处理 

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

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

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

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

geotools的maven引入:

  1. <!-- geotools的远程库 -->
  2. <properties>
  3. <geotools.version>27.0</geotools.version>
  4. </properties>
  5. <repositories>
  6. <repository>
  7. <id>osgeo</id>
  8. <name>OSGeo Release Repository</name>
  9. <url>https://repo.osgeo.org/repository/release/</url>
  10. <snapshots>
  11. <enabled>false</enabled>
  12. </snapshots>
  13. <releases>
  14. <enabled>true</enabled>
  15. </releases>
  16. </repository>
  17. </repositories>
  18. <dependencies>
  19. <!--geotool https://docs.geotools.org/latest/userguide/tutorial/quickstart/maven.html-->
  20. <dependency>
  21. <groupId>org.geotools</groupId>
  22. <artifactId>gt-geojson</artifactId>
  23. <version>${geotools.version}</version>
  24. </dependency>
  25. <dependency>
  26. <groupId>org.geotools</groupId>
  27. <artifactId>gt-main</artifactId>
  28. <version>${geotools.version}</version>
  29. </dependency>
  30. <dependency>
  31. <groupId>org.geotools</groupId>
  32. <artifactId>gt-opengis</artifactId>
  33. <version>${geotools.version}</version>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.geotools</groupId>
  37. <artifactId>gt-referencing</artifactId>
  38. <version>${geotools.version}</version>
  39. </dependency>
  40. <dependency>
  41. <groupId>org.geotools</groupId>
  42. <artifactId>gt-metadata</artifactId>
  43. <version>${geotools.version}</version>
  44. </dependency>
  45. <dependency>
  46. <groupId>org.geotools</groupId>
  47. <artifactId>gt-epsg-hsql</artifactId>
  48. <version>${geotools.version}</version>
  49. </dependency>
  50. </dependencies>

Geotools工具类转换WKB和Geojson

  1. WKBReader reader = new WKBReader( );
  2. Geometry geometry = reader.read(WKBReader.hexToBytes("0101000020E61000002C39382229FD5D4085716007088C3E40"));
  3. // 设置保留6位小数,否则GeometryJSON默认保留4位小数
  4. GeometryJSON geometryJson = new GeometryJSON(7);
  5. String s = geometryJson.toString(geometry);
  6. System.out.println(s);
  7. //{"type":"Point","coordinates":[119.9556356,30.5469975]}
  8. //EWKB->转geojson丢失信息
  9. Geometry read = geometryJson.read("{\"type\":\"Point\",\"coordinates\":[119.9556356,30.5469975]}");
  10. System.out.println(read.toString());
  11. WKBWriter wkbWriter = new WKBWriter();
  12. byte[] write = wkbWriter.write(geometry);
  13. String s1 = WKBWriter.toHex(write);
  14. System.out.println(s1);

2.mybatis-plus类型转换器

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

MyBatis Plus 自动类型转换之TypeHandler

  1. @Data
  2. @ToString
  3. @TableName (value = "test_table",autoResultMap = true)
  4. @ApiModel ("test")
  5. public class TestTable implements Serializable {
  6. private static final long serialVersionUID = 8881418345724766899L;
  7. @TableId(value = "id")
  8. private Integer id;
  9. @ApiModelProperty(value = "二进制WKB数据")
  10. @TableField(value = "position",typeHandler = WKB2GeoJsonTypeHandler.class)
  11. @JsonRawValue
  12. private String position;
  13. @TableField("name")
  14. private String name;
  15. }

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

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

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

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

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

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

添加maven包:

  1. <!-- 这里会补充mybatis缺少的JDBC-Type如postGis中的geometry类型 -->
  2. <dependency>
  3. <groupId>net.postgis</groupId>
  4. <artifactId>postgis-jdbc</artifactId>
  5. <version>2.5.0</version>
  6. </dependency>

类型转换器代码:

  1. package com.zjzy.mapper.typehandler;
  2. import com.zjzy.mapper.CommonCodeMapper;
  3. import com.zjzy.util.SpringContextUtil;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.ibatis.type.JdbcType;
  6. import org.apache.ibatis.type.MappedJdbcTypes;
  7. import org.apache.ibatis.type.MappedTypes;
  8. import org.apache.ibatis.type.TypeHandler;
  9. import org.geotools.geojson.geom.GeometryJSON;
  10. import org.geotools.geometry.jts.WKBReader;
  11. import org.locationtech.jts.geom.Geometry;
  12. import org.locationtech.jts.io.ParseException;
  13. import org.postgis.PGgeometry;
  14. import java.sql.CallableStatement;
  15. import java.sql.PreparedStatement;
  16. import java.sql.ResultSet;
  17. import java.sql.SQLException;
  18. import java.util.Set;
  19. /**
  20. * @version 2.0
  21. * @description
  22. * @Author yaoct
  23. * @create 2021/12/22 16:19
  24. */
  25. @Slf4j
  26. public class WKB2GeoJsonTypeHandler implements TypeHandler<String> {
  27. /**
  28. * 插入数据,转换,geoJson2EWKB
  29. * @param ps
  30. * @param i
  31. * @param parameter
  32. * @param jdbcType
  33. * @throws SQLException
  34. */
  35. @Override
  36. public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
  37. //EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
  38. // CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
  39. // String EWKB = mapper.geo2EWKB(parameter);
  40. // PGgeometry ewkb = new PGgeometry(EWKB);
  41. // ps.setObject(i,ewkb);
  42. //通过geoTool转换WKB
  43. GeometryJSON geometryJson = new GeometryJSON(7);
  44. Geometry read = null;
  45. try {
  46. read = geometryJson.read(parameter);
  47. } catch (IOException e) {
  48. e.printStackTrace();
  49. }
  50. // System.out.println(read.toString());
  51. read.setSRID(4326);
  52. // GeometryJSON geometryJson = new GeometryJSON(7);
  53. WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
  54. byte[] write = wkbWriter.write(read);
  55. String s1 = WKBWriter.toHex(write);
  56. PGgeometry ewkb = new PGgeometry(s1);
  57. ps.setObject(i,ewkb);
  58. }
  59. /**
  60. * 取出数据转换,WKB->Geojson
  61. * @param rs
  62. * @param columnName
  63. * @return
  64. * @throws SQLException
  65. */
  66. @Override
  67. public String getResult(ResultSet rs, String columnName) throws SQLException {
  68. String WKB = rs.getString(columnName);
  69. if(WKB==null){
  70. return null;
  71. }
  72. WKBReader reader = new WKBReader( );
  73. Geometry geometry = null;
  74. try {
  75. geometry = reader.read(WKBReader.hexToBytes(WKB));
  76. } catch (ParseException e) {
  77. //转换失败
  78. return null;
  79. }
  80. //转换成4326
  81. try {
  82. int srid = geometry.getSRID();
  83. CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
  84. CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:4326",true);
  85. MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
  86. geometry = JTS.transform(geometry, transform);
  87. } catch (Exception e) {
  88. e.printStackTrace();
  89. }
  90. // 设置保留6位小数,否则GeometryJSON默认保留4位小数
  91. GeometryJSON geometryJson = new GeometryJSON(7);
  92. return geometryJson.toString(geometry);
  93. }
  94. @Override
  95. public String getResult(ResultSet rs, int columnIndex) throws SQLException {
  96. return null;
  97. }
  98. @Override
  99. public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
  100. return null;
  101. }
  102. }
  1. @Component
  2. public class SpringContextUtil implements ApplicationContextAware {
  3. private static ApplicationContext applicationContext;
  4. @Override
  5. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
  6. SpringContextUtil.applicationContext = applicationContext;
  7. }
  8. //获取applicationContext
  9. public static ApplicationContext getApplicationContext() {
  10. return applicationContext;
  11. }
  12. //通过name获取 Bean.
  13. public static Object getBean(String name) {
  14. return getApplicationContext().getBean(name);
  15. }
  16. //通过class获取Bean.
  17. public static <T> T getBean(Class<T> clazz) {
  18. return getApplicationContext().getBean(clazz);
  19. }
  20. //通过name,以及Clazz返回指定的Bean
  21. public static <T> T getBean(String name, Class<T> clazz) {
  22. return getApplicationContext().getBean(name, clazz);
  23. }
  24. //关闭springboot
  25. public static void close(){
  26. ((ConfigurableApplicationContext)(getApplicationContext())).close();
  27. }
  28. //得到当前线程的HttpServletResponse,可在静态方法中得到
  29. public static HttpServletResponse getHttpServletResponse(){
  30. return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getResponse();
  31. }
  32. //得到当前线程的HttpServletRequest,可在静态方法中得到
  33. public static HttpServletRequest getHttpServletRequest(){
  34. return ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
  35. }
  36. }

  1. @Repository
  2. public interface CommonCodeMapper extends BaseMapper<CommonCode> {
  3. /**
  4. * EWKB是pg数据库自定义的类型,所以需要用数据库函数
  5. * @param geoJson
  6. * @return
  7. */
  8. @Select("select ST_GeomFromGeoJSON(#{geoJson})")
  9. String geo2EWKB(String geoJson);
  10. }

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

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

  1. /**
  2. * 使用ResultMap
  3. */
  4. @Results(id = "userMap", value = {
  5. //可以使用这种方式来处理字段名和数据库表字段名不一致的情况
  6. @Result(column = "username", property = "username", jdbcType=JdbcType.VARCHAR,typeHandler = WKB2GeoJsonTypeHandler.class),
  7. @Result(column = "passwd", property = "passwd", jdbcType=JdbcType.VARCHAR),
  8. @Result(column = "birth_day", property = "birthDay", jdbcType=JdbcType.VARCHAR)
  9. })
  10. @Select("SELECT * FROM t_user WHERE id=#{id}")
  11. User loadByIdResultMap(Long id);
  12. /**
  13. * 引用其他的Result
  14. */
  15. @ResultMap("userMap")
  16. @Select("SELECT * FROM t_user WHERE id=#{id}")
  17. User loadByIdResultMapReference(Long id);

在xml中使用示例示例:

  1. <resultMap id="locationResultMap" type="com.zjzy.model.po.ExaminationApplication">
  2. <result typeHandler="com.zjzy.mapper.typehandler.WKB2GeoJsonTypeHandler" column="dig_position" javaType="String"
  3. property="digPosition"/>
  4. </resultMap>
  5. <select id="selectExaminationApplicationByPage" resultMap="locationResultMap">
  6. </select>

注意:

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

org.postgresql.util.PGobject。

2.对应数据库geometry类型的java类不在PG的JDBC驱动的实现类中,因为geometry类型在PG的扩展postgis中,所以响应的要引入postGIS这部分的驱动,

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方法

 

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

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

  1. package com.zjzy.mapper.typehandler;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.zjzy.util.GisUtil;
  4. import com.zjzy.util.SpringContextUtil;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.apache.ibatis.type.JdbcType;
  7. import org.apache.ibatis.type.TypeHandler;
  8. import org.geotools.geojson.geom.GeometryJSON;
  9. import org.geotools.geometry.jts.JTS;
  10. import org.geotools.geometry.jts.WKBReader;
  11. import org.geotools.referencing.CRS;
  12. import org.locationtech.jts.geom.Geometry;
  13. import org.locationtech.jts.io.ByteOrderValues;
  14. import org.locationtech.jts.io.ParseException;
  15. import org.locationtech.jts.io.WKBWriter;
  16. import org.locationtech.jts.io.WKTWriter;
  17. import org.opengis.referencing.crs.CoordinateReferenceSystem;
  18. import org.opengis.referencing.operation.MathTransform;
  19. import org.postgis.PGbox2d;
  20. import org.postgis.PGgeometry;
  21. import org.postgresql.util.PGobject;
  22. import org.springframework.core.env.Environment;
  23. import java.io.IOException;
  24. import java.sql.CallableStatement;
  25. import java.sql.PreparedStatement;
  26. import java.sql.ResultSet;
  27. import java.sql.SQLException;
  28. /**
  29. * @version 1.0
  30. * @description
  31. * @Author yaoct
  32. * @create 2021/12/22 16:19
  33. */
  34. @Slf4j
  35. public class WKB2GeoJsonTypeHandler implements TypeHandler<String> {
  36. /**
  37. * 插入数据,转换,geoJson2EWKB
  38. * @param ps
  39. * @param i
  40. * @param parameter
  41. * @param jdbcType
  42. * @throws SQLException
  43. */
  44. @Override
  45. public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
  46. //EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
  47. // CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
  48. // String EWKB = mapper.geo2EWKB(parameter);
  49. // PGgeometry ewkb = new PGgeometry(EWKB);
  50. // ps.setObject(i,ewkb);
  51. //通过geoTool转换WKB
  52. GeometryJSON geometryJson = new GeometryJSON(7);
  53. Geometry geometry = null;
  54. try {
  55. geometry = geometryJson.read(parameter);
  56. } catch (IOException e) {
  57. e.printStackTrace();
  58. }
  59. // System.out.println(read.toString());
  60. geometry.setSRID(4326);
  61. // GeometryJSON geometryJson = new GeometryJSON(7);
  62. //方式1.基于net.postgis
  63. // WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
  64. // byte[] write = wkbWriter.write(geometry);
  65. // String s1 = WKBWriter.toHex(write);
  66. // PGgeometry ewkb = new PGgeometry(s1);//EWKB比WKB多了SRID头字符串,PGgeometry.toString()会自动添加SRID
  67. // ps.setObject(i,ewkb);
  68. //方式2.设置ewkb,Postgresql驱动会先去数据库 pg_catalog.pg_type 查出geometry的类型id,这里的geometry字符串对应数据库pg_catalog.pg_type表中的geometry
  69. //以下方式不用导入net.postgis包
  70. // PGobject pGobject = new PGobject();
  71. // pGobject.setType("geometry");
  72. // pGobject.setValue(s1);
  73. // ps.setObject(i,pGobject);
  74. //方式3.设置拼接ewkt
  75. //以下方式不用导入net.postgis包,ewkb太长会超出sql限制,以下转换为ewkt
  76. PGobject pGobject = new PGobject();
  77. pGobject.setType("geometry");
  78. String pre="SRID="+4326+";";
  79. pGobject.setValue(pre+GisUtil.Geometry2WKT(geometry));
  80. ps.setObject(i,pGobject);
  81. }
  82. /**
  83. * 取出数据转换,WKB->Geojson
  84. * @param rs
  85. * @param columnName
  86. * @return
  87. * @throws SQLException
  88. */
  89. @Override
  90. public String getResult(ResultSet rs, String columnName) throws SQLException {
  91. String WKB = rs.getString(columnName);
  92. if(WKB==null){
  93. return null;
  94. }
  95. WKBReader reader = new WKBReader( );
  96. Geometry geometry = null;
  97. try {
  98. geometry = reader.read(WKBReader.hexToBytes(WKB));
  99. } catch (ParseException e) {
  100. //转换失败
  101. return null;
  102. }
  103. //转换成4326
  104. try {
  105. int srid = geometry.getSRID();
  106. if(srid==0)srid=4549;//默认4549
  107. int targetSrid=4326;//默认4326
  108. Environment environment = SpringContextUtil.getBean(Environment.class);
  109. if(environment!=null){
  110. String sridTarget = environment.getProperty("sridTarget");
  111. if(sridTarget!=null){
  112. try {
  113. targetSrid=Integer.valueOf(sridTarget);
  114. } catch (Exception e){
  115. //转换失败
  116. }
  117. }
  118. }
  119. CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
  120. CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:"+targetSrid,true);
  121. MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
  122. geometry = JTS.transform(geometry, transform);
  123. } catch (Exception e) {
  124. e.printStackTrace();
  125. }
  126. // 设置保留6位小数,否则GeometryJSON默认保留4位小数
  127. GeometryJSON geometryJson = new GeometryJSON(7);
  128. String json = geometryJson.toString(geometry);
  129. JSONObject jsonObject = JSONObject.parseObject(json);
  130. jsonObject.put("srid",geometry.getSRID());
  131. return jsonObject.toJSONString();
  132. }
  133. @Override
  134. public String getResult(ResultSet rs, int columnIndex) throws SQLException {
  135. return null;
  136. }
  137. @Override
  138. public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
  139. return null;
  140. }
  141. }
  1. package com.zjzy.util;
  2. import org.geotools.geojson.geom.GeometryJSON;
  3. import org.geotools.geometry.jts.JTS;
  4. import org.geotools.geometry.jts.WKBReader;
  5. import org.geotools.referencing.CRS;
  6. import org.geotools.referencing.GeodeticCalculator;
  7. import org.geotools.referencing.crs.DefaultGeographicCRS;
  8. import org.locationtech.jts.geom.Geometry;
  9. import org.locationtech.jts.io.*;
  10. import org.opengis.referencing.FactoryException;
  11. import org.opengis.referencing.crs.CoordinateReferenceSystem;
  12. import org.opengis.referencing.operation.MathTransform;
  13. import org.opengis.referencing.operation.TransformException;
  14. import java.io.IOException;
  15. /**
  16. * @Author yaoct
  17. * @Date 2022/9/16 10:55
  18. * @Version 1.0
  19. * @description
  20. */
  21. public class GisUtil {
  22. /**
  23. * WKB字符串转Geometry格式
  24. * @param WKB
  25. * @return
  26. */
  27. public static Geometry WKB2Geometry(String WKB){
  28. WKBReader reader = new WKBReader();
  29. Geometry geometry = null;
  30. try {
  31. geometry = reader.read(WKBReader.hexToBytes(WKB));
  32. } catch (ParseException e) {
  33. //转换失败
  34. throw new RuntimeException("转换失败",e);
  35. }
  36. return geometry;
  37. }
  38. /**
  39. * Geometry格式转WKB字符串
  40. * @param geometry
  41. * @return
  42. */
  43. public static String Geometry2WKB(Geometry geometry){
  44. WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
  45. byte[] write = wkbWriter.write(geometry);
  46. String ret = WKBWriter.toHex(write);
  47. return ret;
  48. }
  49. /**
  50. * WKT字符串转Geometry格式
  51. * @param WKT
  52. * @return
  53. */
  54. public static Geometry WKT2Geometry(String WKT){
  55. WKTReader reader = new WKTReader();
  56. Geometry geometry = null;
  57. try {
  58. geometry = reader.read(WKT);
  59. } catch (ParseException e) {
  60. //转换失败
  61. throw new RuntimeException("转换失败",e);
  62. }
  63. return geometry;
  64. }
  65. /**
  66. * Geometry格式转WKT字符串
  67. * @param geometry
  68. * @return
  69. */
  70. public static String Geometry2WKT(Geometry geometry){
  71. WKTWriter wktWriter = new WKTWriter();
  72. String wkt= wktWriter.write(geometry);
  73. return wkt;
  74. }
  75. /**
  76. * 转换Geometry坐标
  77. * @param geometry
  78. * @param targetSrid 新坐标
  79. * @return
  80. */
  81. public static Geometry coordinateTransfer(Geometry geometry, int targetSrid){
  82. int originSrid = geometry.getSRID();
  83. CoordinateReferenceSystem sourceCRS = null;
  84. CoordinateReferenceSystem targetCRS = null;
  85. MathTransform transform=null;
  86. try {
  87. sourceCRS = CRS.decode("EPSG:"+originSrid,true);
  88. targetCRS = CRS.decode("EPSG:"+targetSrid,true);
  89. transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
  90. } catch (FactoryException e) {
  91. throw new RuntimeException("坐标错误",e);
  92. }
  93. Geometry ret = null;
  94. try {
  95. ret = JTS.transform(geometry, transform);
  96. } catch (TransformException e) {
  97. throw new RuntimeException("坐标转换错误",e);
  98. }
  99. return ret;
  100. }
  101. /**
  102. * Geometry->geoJson
  103. * @param geometry
  104. * @return
  105. */
  106. public static String geometry2GeoJson(Geometry geometry){
  107. // 设置保留6位小数,否则GeometryJSON默认保留4位小数
  108. GeometryJSON geometryJson = new GeometryJSON(7);
  109. String json = geometryJson.toString(geometry);
  110. // JSONObject jsonObject = JSONObject.parseObject(json);
  111. // jsonObject.put("srid",geometry.getSRID());
  112. // return jsonObject.toJSONString();
  113. return json;
  114. }
  115. /**
  116. * geoJson->Geometry
  117. * @param geoJson
  118. * @return
  119. */
  120. public static Geometry geoJson2Geometry(String geoJson){
  121. GeometryJSON geometryJson = new GeometryJSON(7);
  122. Geometry ret=null;
  123. try {
  124. Geometry read = geometryJson.read(geoJson);
  125. } catch (IOException e) {
  126. throw new RuntimeException("转换失败",e);
  127. }
  128. return ret;
  129. }
  130. /**
  131. * 计算两点间的距离
  132. * @param lon1
  133. * @param lat1
  134. * @param lon2
  135. * @param lat2
  136. * @return
  137. */
  138. public static double calculateDistance(double lon1,double lat1,double lon2,double lat2){
  139. //CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
  140. GeodeticCalculator geodeticCalculator = new GeodeticCalculator(DefaultGeographicCRS.WGS84);
  141. // 起点经纬度
  142. geodeticCalculator.setStartingGeographicPoint(lon1,lat1);
  143. // 末点经纬度
  144. geodeticCalculator.setDestinationGeographicPoint(lon2,lat2);
  145. // 计算距离,单位:米
  146. double distance = geodeticCalculator.getOrthodromicDistance();
  147. return distance;
  148. }
  149. }

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

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

  1. package com.wisdomcity.laian.monitor.mapper.typehandler;
  2. import com.alibaba.fastjson.JSONObject;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import com.fhs.common.spring.SpringContextUtil;
  5. import com.kingbase8.util.KBobject;
  6. import com.wisdomcity.laian.monitor.utils.GisUtil;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.apache.ibatis.type.JdbcType;
  9. import org.apache.ibatis.type.TypeHandler;
  10. import org.geotools.geojson.geom.GeometryJSON;
  11. import org.geotools.geometry.jts.JTS;
  12. import org.geotools.geometry.jts.WKBReader;
  13. import org.geotools.referencing.CRS;
  14. import org.locationtech.jts.geom.Geometry;
  15. import org.locationtech.jts.io.ByteOrderValues;
  16. import org.locationtech.jts.io.ParseException;
  17. import org.locationtech.jts.io.WKBWriter;
  18. import org.opengis.referencing.crs.CoordinateReferenceSystem;
  19. import org.opengis.referencing.operation.MathTransform;
  20. import java.io.IOException;
  21. import java.sql.CallableStatement;
  22. import java.sql.PreparedStatement;
  23. import java.sql.ResultSet;
  24. import java.sql.SQLException;
  25. import java.util.Map;
  26. /**
  27. * @version 1.0
  28. * @description
  29. * @Author yaoct
  30. * @create 2021/12/22 16:19
  31. */
  32. @Slf4j
  33. public class WKB2GeoJsonTypeHandler implements TypeHandler<Map> {
  34. /**
  35. * 插入数据,转换,geoJson2EWKB
  36. * @param ps
  37. * @param i
  38. * @param parameter
  39. * @param jdbcType
  40. * @throws SQLException
  41. */
  42. @Override
  43. public void setParameter(PreparedStatement ps, int i, Map parameter, JdbcType jdbcType) throws SQLException {
  44. //EWKB是pg数据库自定义的类型,所以需要用数据库函数,插入数据库一般次数较少,这样并不会对数据库造成过大负担
  45. // CommonCodeMapper mapper = SpringContextUtil.getBean(CommonCodeMapper.class);
  46. // String EWKB = mapper.geo2EWKB(parameter);
  47. // PGgeometry ewkb = new PGgeometry(EWKB);
  48. // ps.setObject(i,ewkb);
  49. //通过geoTool转换WKB
  50. GeometryJSON geometryJson = new GeometryJSON(7);
  51. Geometry geometry = null;
  52. try {
  53. geometry = geometryJson.read(JSONObject.toJSONString(parameter));
  54. } catch (IOException e) {
  55. e.printStackTrace();
  56. }
  57. // System.out.println(read.toString());
  58. geometry.setSRID(4326);
  59. // GeometryJSON geometryJson = new GeometryJSON(7);
  60. //方式1.基于net.postgis
  61. WKBWriter wkbWriter = new WKBWriter(2, ByteOrderValues.BIG_ENDIAN,true);
  62. byte[] write = wkbWriter.write(geometry);
  63. String s1 = WKBWriter.toHex(write);
  64. // PGgeometry ewkb = new PGgeometry(s1);//EWKB比WKB多了SRID头字符串,PGgeometry.toString()会自动添加SRID
  65. // ps.setObject(i,ewkb);
  66. //方式2.设置ewkb,Postgresql驱动会先去数据库 pg_catalog.pg_type 查出geometry的类型id,这里的geometry字符串对应数据库pg_catalog.pg_type表中的geometry
  67. // 以下方式不用导入net.postgis包
  68. // PGobject pGobject = new PGobject();
  69. // pGobject.setType("geometry");
  70. // pGobject.setValue(s1);
  71. // ps.setObject(i,pGobject);
  72. //方式3.设置拼接ewkt
  73. //以下方式不用导入net.postgis包,ewkb太长会超出sql限制,以下转换为ewkt
  74. // PGobject pGobject = new PGobject();
  75. // pGobject.setType("geometry");
  76. // String pre="SRID="+4326+";";
  77. // pGobject.setValue(pre+GisUtil.Geometry2WKT(geometry));
  78. // ps.setObject(i,pGobject);
  79. KBobject pGobject = new KBobject();
  80. pGobject.setType("geometry");
  81. String pre="SRID="+4326+";";
  82. pGobject.setValue(pre+ GisUtil.Geometry2WKT(geometry));
  83. ps.setObject(i,pGobject);
  84. }
  85. /**
  86. * 取出数据转换,WKB->Geojson
  87. * @param rs
  88. * @param columnName
  89. * @return
  90. * @throws SQLException
  91. */
  92. @Override
  93. public Map getResult(ResultSet rs, String columnName) throws SQLException {
  94. String WKB = rs.getString(columnName);
  95. if(WKB==null){
  96. return null;
  97. }
  98. WKBReader reader = new WKBReader( );
  99. Geometry geometry = null;
  100. try {
  101. geometry = reader.read(WKBReader.hexToBytes(WKB));
  102. } catch (ParseException e) {
  103. //转换失败
  104. return null;
  105. }
  106. //转换成4326
  107. try {
  108. int srid = geometry.getSRID();
  109. // if(srid==0)srid=4549;//默认4549
  110. int targetSrid=4326;//默认4326
  111. // Environment environment = SpringContextUtil.getBean(Environment.class);
  112. // if(environment!=null){
  113. // String sridTarget = environment.getProperty("sridTarget");
  114. // if(sridTarget!=null){
  115. // try {
  116. // targetSrid=Integer.valueOf(sridTarget);
  117. // } catch (Exception e){
  118. // //转换失败
  119. // }
  120. // }
  121. // }
  122. if(srid!=targetSrid&&srid!=0){
  123. CoordinateReferenceSystem sourceCRS = CRS.decode("EPSG:"+srid,true);
  124. CoordinateReferenceSystem targetCRS = CRS.decode("EPSG:"+targetSrid,true);
  125. MathTransform transform = CRS.findMathTransform(sourceCRS, targetCRS,true);
  126. geometry = JTS.transform(geometry, transform);
  127. geometry.setSRID(targetSrid);
  128. }
  129. } catch (Exception e) {
  130. e.printStackTrace();
  131. }
  132. // 设置保留6位小数,否则GeometryJSON默认保留4位小数
  133. GeometryJSON geometryJson = new GeometryJSON(7);
  134. String json = geometryJson.toString(geometry);
  135. // JSONObject jsonObject = JSONObject.parseObject(json);
  136. // jsonObject.put("srid",geometry.getSRID());
  137. // return jsonObject.toJSONString();
  138. return JSONObject.parseObject(json);
  139. }
  140. @Override
  141. public Map getResult(ResultSet rs, int columnIndex) throws SQLException {
  142. return null;
  143. }
  144. @Override
  145. public Map getResult(CallableStatement cs, int columnIndex) throws SQLException {
  146. return null;
  147. }
  148. }

实体类字段改为 :

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

xml中使用

  1. <resultMap id="locationResultMap" type="com.wisdomcity.laian.monitor.model.supply.po.SupplyPipePoint">
  2. <result typeHandler="com.wisdomcity.laian.monitor.mapper.typehandler.WKB2GeoJsonTypeHandler" column="geom" javaType="Map"
  3. property="geom"/>
  4. </resultMap>

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

参考:

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常用注解

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/870363
推荐阅读
相关标签
  

闽ICP备14008679号