mysql中geometry字段的查询和保存

本文介绍了如何在MySQL中利用geometry类型和相关函数处理地理位置信息,包括存储、查询和操作。通过mybatis的autoResultMap配置及GeometryTypeHandler处理WKT和WKB格式,实现了与Java的交互。文章强调了使用MySQL的几何函数如ST_Contains、ST_Distance等进行空间分析,并提供了JTS工具类的实现细节。

有段时间为了追求效率,把用es相关的地理位置功能都去掉了,使用mysql已有的geometry的功能做地理位置,mybatis这块

@TableName(value = "t_event_info",autoResultMap = true)
如果使用复杂的数据结构,json,有两个方式
1、使用xml的是要 resultMap
2、没有使用xml的 必须配置autoResultMap=true

地理相关的函数https://dev.mysql.com/doc/refman/8.0/en/spatial-function-reference.html
姓名描述介绍
GeomCollection()从几何构造几何集合
GeometryCollection()从几何构造几何集合
LineString()从点值构造 LineString
MBRContains()一个几何的 MBR 是否包含另一个几何的 MBR
MBRCoveredBy()一个 MBR 是否被另一个覆盖
MBRCovers()一个 MBR 是否覆盖另一个
MBRDisjoint()两个几何的 MBR 是否不相交
MBREquals()两个几何的 MBR 是否相等
MBRIntersects()两个几何的 MBR 是否相交
MBROverlaps()两个几何的 MBR 是否重叠
MBRTouches()两个几何的 MBR 是否接触
MBRWithin()一个几何的 MBR 是否在另一个几何的 MBR 内
MultiLineString()从 LineString 值构造 MultiLineString
MultiPoint()从点值构造多点
MultiPolygon()从 Polygon 值构造 MultiPolygon
Point()从坐标构造点
Polygon()从 LineString 参数构造多边形
ST_Area()返回多边形或多多边形区域
ST_AsBinary(), ST_AsWKB()从内部几何格式转换为 WKB
ST_AsGeoJSON()从几何生成 GeoJSON 对象
ST_AsText(),ST_AsWKT()从内部几何格式转换为 WKT
ST_Buffer()返回几何给定距离内的点的几何
ST_Buffer_Strategy()为 ST_Buffer() 生成策略选项
ST_Centroid()将质心作为一个点返回
ST_Collect()将空间值聚合到集合中8.0.24
ST_Contains()一个几何图形是否包含另一个几何图形
ST_ConvexHull()返回几何的凸包
ST_Crosses()一个几何图形是否与另一个几何图形相交
ST_Difference()两个几何形状的返回点集差异
ST_Dimension()几何尺寸
ST_Disjoint()一个几何图形是否与另一个几何图形脱节
ST_Distance()一个几何体与另一个几何体的距离
ST_Distance_Sphere()地球上两个几何图形之间的最小距离
ST_EndPoint()线串的终点
ST_Envelope()返回几何的 MBR
ST_Equals()一个几何图形是否等于另一个几何图形
ST_ExteriorRing()返回 Polygon 的外环
ST_FrechetDistance()一个几何体与另一个几何体的离散 Fréchet 距离8.0.23
ST_GeoHash()产生一个geohash值
ST_GeomCollFromText(), ST_GeometryCollectionFromText(), ST_GeomCollFromTxt()从 WKT 返回几何集合
ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB()从 WKB 返回几何集合
ST_GeometryN()从几何集合中返回第 N 个几何
ST_GeometryType()返回几何类型的名称
ST_GeomFromGeoJSON()从 GeoJSON 对象生成几何
ST_GeomFromText(), ST_GeometryFromText()从 WKT 返回几何图形
ST_GeomFromWKB(),ST_GeometryFromWKB()从 WKB 返回几何图形
ST_HausdorffDistance()一个几何体与另一个几何体的离散豪斯多夫距离8.0.23
ST_InteriorRingN()返回 Polygon 的第 N 个内环
ST_Intersection()返回点集两个几何的交集
ST_Intersects()一个几何图形是否与另一个几何图形相交
ST_IsClosed()几何是否封闭且简单
ST_IsEmpty()几何是否为空
ST_IsSimple()几何是否简单
ST_IsValid()几何是否有效
ST_LatFromGeoHash()从 geohash 值返回纬度
ST_Latitude()返回Point的纬度8.0.12
ST_Length()LineString 的返回长度
ST_LineFromText(),ST_LineStringFromText()从 WKT 构造 LineString
ST_LineFromWKB(),ST_LineStringFromWKB()从 WKB 构造 LineString
ST_LineInterpolatePoint()沿 LineString 的给定百分比的点8.0.24
ST_LineInterpolatePoints()沿 LineString 的给定百分比的点8.0.24
ST_LongFromGeoHash()从 geohash 值返回经度
ST_Longitude()返回Point的经度8.0.12
ST_MakeEnvelope()围绕两个点的矩形
ST_MLineFromText(), ST_MultiLineStringFromText()从 WKT 构造 MultiLineString
ST_MLineFromWKB(),ST_MultiLineStringFromWKB()从 WKB 构造 MultiLineString
ST_MPointFromText(),ST_MultiPointFromText()从 WKT 构造多点
ST_MPointFromWKB(),ST_MultiPointFromWKB()从 WKB 构造多点
ST_MPolyFromText(),ST_MultiPolygonFromText()从 WKT 构造 MultiPolygon
ST_MPolyFromWKB(),ST_MultiPolygonFromWKB()从 WKB 构造 MultiPolygon
ST_NumGeometries()返回几何集合中的几何数
ST_NumInteriorRing(),ST_NumInteriorRings()返回 Polygon 中的内环数
ST_NumPoints()返回 LineString 中的点数
ST_Overlaps()一个几何图形是否与另一个几何图形重叠
ST_PointAtDistance()沿 LineString 给定距离的点8.0.24
ST_PointFromGeoHash()将 geohash 值转换为 POINT 值
ST_PointFromText()从 WKT 构造点
ST_PointFromWKB()从 WKB 构造点
ST_PointN()从 LineString 返回第 N 个点
ST_PolyFromText(), ST_PolygonFromText()从 WKT 构造多边形
ST_PolyFromWKB(),ST_PolygonFromWKB()从 WKB 构造多边形
ST_Simplify()返回简化几何
ST_SRID()返回几何的空间参考系统 ID
ST_StartPoint()线串的起点
ST_SwapXY()交换 X/Y 坐标的返回参数
ST_SymDifference()返回点设置两个几何的对称差
ST_Touches()一个几何图形是否接触另一个几何图形
ST_Transform()变换几何坐标8.0.13
ST_Union()返回点集两个几何的并集
ST_Validate()返回经过验证的几何图形
ST_Within()一个几何体是否在另一个几何体中
ST_X()返回Point的X坐标
ST_Y()返回Point的Y坐标

geometry的类型

MySQL 具有对应于 OpenGIS 类的空间数据类型。

一些空间数据类型包含单个几何值:

  • GEOMETRY

  • POINT

  • LINESTRING

  • POLYGON

GEOMETRY可以存储任何类型的几何值。其他单值类型(POINT、 LINESTRINGPOLYGON)将它们的值限制为特定的几何类型。

其他空间数据类型包含值的集合:

  • MULTIPOINT

  • MULTILINESTRING

  • MULTIPOLYGON

  • GEOMETRYCOLLECTION

GEOMETRYCOLLECTION可以存储任何类型的对象的集合。其他集合类型(MULTIPOINT、 MULTILINESTRING和 MULTIPOLYGON)将集合成员限制为具有特定几何类型的成员。

  • Well-Known Text (WKT) format 文本

  • Well-Known Binary (WKB) format 二进制

    domain

     @TableField(value = "main_geo",typeHandler = GeometryTypeHandler.class)
     private String mainGeo;

    handler
     

    @Slf4j
    @MappedTypes(value = {String.class})
    public class GeometryTypeHandler extends BaseTypeHandler {
    
        @Override
        public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object o, JdbcType jdbcType) throws SQLException {
            WKTReader wktReader= SpringUtil.getBean(WKTReader.class);
            try {
            Geometry pointGeo = wktReader.read(o.toString());
            WKBWriter wkbWriter= SpringUtil.getBean(WKBWriter.class);
            byte[] writer = wkbWriter.write(pointGeo);
            byte[] wkb=new byte[writer.length+4];
            ByteOrderValues.putInt(4326, wkb, ByteOrderValues.LITTLE_ENDIAN);
            System.arraycopy(writer,0,wkb,4,writer.length);
            preparedStatement.setBytes(i, wkb);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    /**
     * 获取jts包对象的wkt文本,再转换成sqlserver的Geometry对象
     * 调用ps的setBytes()方法,以二进制持久化该geometry对象
    
     */
    
        @Override
    
        public String getNullableResult(ResultSet resultSet, String s) {
    
            try {
    /**
     * 从ResultSet中读取二进制转换为SqlServer的Geometry对象
     * 使用jts的WKTReader将wkt文本转成jts的Geometryd对象
     */
                WKBReader wkbReader= SpringUtil.getBean(WKBReader.class);
                byte[] bytes = resultSet.getBytes(s);
                byte[] bytesN = new byte[bytes.length-4];
                System.arraycopy(bytes,4,bytesN,0,bytes.length-4);
                Geometry geometry = wkbReader.read(bytesN);
                return geometry.toText();
            } catch (Exception e) {
                log.error(e.getMessage());
            }
            return null;
        }
    
        @Override
        public String getNullableResult(ResultSet resultSet, int i) throws SQLException {
            return null;
        }
    
        @Override
        public String getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
            return null;
        }

    工具类申明
     

    @Component
    @ComponentScan(value = {"cn.hutool.extra.spring"})
    @Import(SpringUtil.class)
    public class JTSBean {
    
        private GeometryFactory geometryFactory;
    
        public JTSBean() {
            geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
        }
    
        @Bean
        public WKBWriter wkbWriter() {
            return new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN);
        }
    
        @Bean
        public WKBReader wkbReader() {
            return new WKBReader(geometryFactory);
        }
    
        @Bean
        public WKTReader wktReader() {
            return new WKTReader(geometryFactory);
        }
    }

    有两点注意,
    1、整数 SRID (0) 的 4 个字节的值 必须与GeometryFactory声明的一致
    2、WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN) 从低端写入 (不大确定)

虽然所给引用主要围绕PostGis空间数据库,但处理MySQLgeometry类型数据也有一些通用思路可借鉴。 ### 1. 自定义TypeHandler 可参考在PostGis中自定义TypeHandler的方式,在MyBatis-Plus里自定义处理geometry类型数据的TypeHandler。在处理PostGis时,需要自定义`GeometryTypeHandler`,在处理MySQLgeometry类型数据时,同样要编写一个能将Java对象MySQLgeometry类型数据进行相互转换的TypeHandler。 ```java import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.*; import java.util.Objects; public class MySQLGeometryTypeHandler extends BaseTypeHandler<Object> { @Override public void setNonNullParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException { // 将Java对象转换为MySQLgeometry类型数据并设置到PreparedStatement中 if (Objects.nonNull(parameter)) { // 这里需要根据实际的Java对象类型转换逻辑来实现 // 示例代码,假设parameter是一个包含几何信息的对象 String wkt = convertToWKT(parameter); ps.setString(i, wkt); } } @Override public Object getNullableResult(ResultSet rs, String columnName) throws SQLException { // 从ResultSet中获取MySQLgeometry类型数据并转换为Java对象 String wkt = rs.getString(columnName); return convertFromWKT(wkt); } @Override public Object getNullableResult(ResultSet rs, int columnIndex) throws SQLException { String wkt = rs.getString(columnIndex); return convertFromWKT(wkt); } @Override public Object getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { String wkt = cs.getString(columnIndex); return convertFromWKT(wkt); } private String convertToWKT(Object parameter) { // 实现将Java对象转换为WKT字符串的逻辑 return null; } private Object convertFromWKT(String wkt) { // 实现将WKT字符串转换为Java对象的逻辑 return null; } } ``` ### 2. 配置TypeHandler 在`application.yml`或者`application.properties`中配置自定义TypeHandler的包路径,让MyBatis-Plus能够识别并使用自定义的TypeHandler。 ```yaml mybatis-plus: type-handlers-package: com.example.handler # 自定义TypeHandler所在的包路径 ``` ### 3. 实体类Mapper接口 在实体类中,将对应的geometry类型字段标注为使用自定义的TypeHandler。 ```java import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; @TableName("your_table_name") public class YourEntity { private Long id; @TableField(typeHandler = MySQLGeometryTypeHandler.class) private Object geometry; // gettersetter方法 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public Object getGeometry() { return geometry; } public void setGeometry(Object geometry) { this.geometry = geometry; } } ``` 定义Mapper接口,可参考在PostGis中定义Mapper接口的方式,使用MyBatis-Plus的`BaseMapper`。 ```java import com.baomidou.mybatisplus.core.mapper.BaseMapper; public interface YourEntityMapper extends BaseMapper<YourEntity> { // 可根据需求添加自定义的查询方法 } ``` ### 4. 数据查询插入 在进行数据查询插入时,MyBatis-Plus会自动使用自定义的TypeHandler进行数据的转换。 ```java import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class YourEntityService { @Autowired private YourEntityMapper yourEntityMapper; public List<YourEntity> queryEntities() { QueryWrapper<YourEntity> queryWrapper = new QueryWrapper<>(); return yourEntityMapper.selectList(queryWrapper); } public void insertEntity(YourEntity entity) { yourEntityMapper.insert(entity); } } ```
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大巨魔战将

如果对您有帮助,请打赏1分钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值