mysql中geometry字段的查询和保存

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有段时间为了追求效率,把用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) 从低端写入 (不大确定)

### MyBatisMySQL Geometry 类型字段的映射与处理 在 MyBatis 中处理 MySQL 的 `Geometry` 类型字段,通常需要自定义类型处理器 (`TypeHandler`) 来实现数据类型的转换。以下是详细的解决方案: #### 1. 自定义 TypeHandler 为了支持 MySQL 的 `Geometry` 类型字段,可以编写一个继承自 `BaseTypeHandler<Geometry>` 的类来完成几何对象的序列化反序列化。 ```java import com.vividsolutions.jts.geom.Geometry; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class MysqlGeoPointTypeHandler extends BaseTypeHandler<Geometry> { @Override public void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException { ps.setObject(i, parameter); } @Override public Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException { return (Geometry) rs.getObject(columnName); } @Override public Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException { return (Geometry) rs.getObject(columnIndex); } @Override public Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { return (Geometry) cs.getObject(columnIndex); } } ``` 此代码片段展示了如何通过 JDBC 对象操作 `Geometry` 数据[^4]。 #### 2. 注册 TypeHandler 为了让 MyBatis 使用上述自定义的 `TypeHandler`,需将其注册到 MyBatis 的配置文件或 Java 配置中。 如果使用 XML 配置: ```xml <typeHandlers> <typeHandler handler="com.example.MysqlGeoPointTypeHandler" javaType="com.vividsolutions.jts.geom.Geometry"/> </typeHandlers> ``` 如果是基于 Spring Boot 的项目,则可以通过如下方式动态注册: ```java @Bean public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); // 注册自定义 TypeHandler sessionFactory.setTypeHandlers(new TypeHandler[]{new MysqlGeoPointTypeHandler()}); return sessionFactory.getObject(); } ``` 这一步骤确保了 MyBatis 能够识别并正确解析 `Geometry` 类型的数据[^5]。 #### 3. 实体类设计 在实体类中声明 `Geometry` 类型字段,并提供相应的 Getter Setter 方法。 ```java import com.vividsolutions.jts.geom.Geometry; public class Location { private Long id; private String name; private Geometry geometry; // Getters and Setters public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Geometry getGeometry() { return geometry; } public void setGeometry(Geometry geometry) { this.geometry = geometry; } } ``` 该部分描述了如何构建能够映射数据库表结构的实体类[^2]。 #### 4. Mapper 接口定义 最后,在 Mapper 文件中定义 SQL 查询语句时无需特别关注 `Geometry` 字段的具体细节,因为这些已经由自定义的 `TypeHandler` 完成处理。 ```xml <select id="selectLocationById" resultType="com.example.Location"> SELECT * FROM location WHERE id = #{id} </select> <insert id="insertLocation"> INSERT INTO location(name, geometry) VALUES(#{name}, ST_GeomFromText(#{geometry.wkt})) </insert> ``` 这里需要注意的是,对于插入操作可能需要用函数如 `ST_GeomFromText()` 将 WKT(Well-Known Text)字符串转化为实际的几何对象[^3]。 --- ### 总结 以上方案涵盖了从自定义 `TypeHandler` 到其注册过程以及最终实体类的设计等多个方面,从而实现了 MyBatis 对于 MySQL `Geometry` 类型的支持。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大巨魔战将

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

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

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

打赏作者

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

抵扣说明:

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

余额充值