当前位置: 首页 > news >正文

Spring Boot + MyBatis plus + MySQL 实现位置直线距离实时计算

一、背景

        在一些服务类系统开发时,难免遇到一些服务者和客户之间的一些距离计算,更方便的让服务者了解客户的地址,更好的方式就是调用地图sdk或者api实现,但有些需要通过接口查看多个地点的直线距离时,接口请求会比较多,比如我当前接入的地图接口,每秒请求不能超过三次,因此不符合我们一次查多个地点的位置;所以需要借助其他方式实现;

二、解决方案

       1. 在表结构中添加字段

在添加的字段中存客户的经纬度坐标,前提是客户的位置是固定的,字段类型为point类型

添加字段脚本为

ALTER TABLE merchant_shop ADD COLUMN geo_point POINT  null comment '地理坐标';
ALTER TABLE merchant_shop ADD SPATIAL INDEX idx_geo_point(geo_point);

2.在表结构对应实体添加位置字段

  /*** MybatisX 会自动识别 POINT 类型,并使用对应的 TypeHandler* 它通常会引入 org.locationtech.jts.geom.Point*/@TableField(value = "geo_point",typeHandler = GeoPointTypeHandler.class // 引用你自己的TypeHandler)private Point geoPoint;

3.引入集合空间计算和分析依赖

        JTS(Java Topology Suite)库是一个强大的几何处理工具,提供了丰富的几何对象创建、操作和分析功能。通过JTS,你可以进行各种几何计算和空间分析,并将几何对象转换为标准的WKT格式以便于存储和传输。在实际应用中,JTS广泛用于地理信息系统(GIS)、地图服务和空间数据处理等领域。

  <dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.18.2</version> <!-- 建议使用较新版本 --></dependency>

4.自定实现TypeHandler,处理经纬度坐标

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.PrecisionModel;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKBReader;
import org.locationtech.jts.io.WKTReader;import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;public class GeoPointTypeHandler  extends BaseTypeHandler<Point> {// SRID 4326 对应 WGS84 坐标系 (GPS 使用的坐标系)public static final GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);private static final WKBReader wkbReader = new WKBReader(geometryFactory);private static final WKTReader wktReader = new WKTReader(geometryFactory);@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Point parameter, JdbcType jdbcType) throws SQLException {// 将 Java 的 Point 对象写入数据库ps.setObject(i, parameter);}@Overridepublic Point getNullableResult(ResultSet rs, String columnName) throws SQLException {return getPointFromResultSet(rs.getObject(columnName));}@Overridepublic Point getNullableResult(ResultSet rs, int columnIndex) throws SQLException {return getPointFromResultSet(rs.getObject(columnIndex));}@Overridepublic Point getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {return getPointFromResultSet(cs.getObject(columnIndex));}/*** 从数据库返回的对象中解析出 Point 对象* 数据库驱动可能返回 byte[] (WKB) 或 String (WKT)*/private Point getPointFromResultSet(Object obj) throws SQLException {if (obj == null) {return null;}if (obj instanceof Point) {return (Point) obj;}try {if (obj instanceof byte[]) {// 处理 WKB (Well-Known Binary) 格式return (Point) wkbReader.read((byte[]) obj);} else if (obj instanceof String) {// 处理 WKT (Well-Known Text) 格式, e.g., "POINT(103.87 36.05)"return (Point) wktReader.read((String) obj);}} catch (ParseException e) {throw new SQLException("Error parsing geometry from database: " + e.getMessage(), e);}throw new SQLException("Unsupported geometry type returned from database: " + obj.getClass().getName());}
}

5.通过SQL脚本查询实现,查询过程使用MySQL现有函数ST_Distance_Sphere

        ST_Distance_Sphere 是MySQL中的一个空间函数,它用于计算球面上两点之间的最小距离。这个函数非常有用,特别是在处理地理位置数据时,比如计算两个地点之间的直线距离

 SELECT  ms.*, ST_Distance_Sphere(geo_point,POINT(#{latValue}, #{lngValue})) AS linearDistanceFROM merchant_shop ms

注:latValue 为当前位置的精度, lngValue为当前位置的维度;

通过以上方案可以实现距离计算,就可以不用频繁调用三方地图接口;

http://www.dtcms.com/a/426944.html

相关文章:

  • 大数据Spark(六十四):Spark算子介绍
  • 网页网站设计制作微信推广网站
  • WPF——效果和可视化对象
  • WPF 具有跨线程功能的UI元素
  • 河北众成建设有限公司网站做dw网站图片怎么下载地址
  • PHP基础-函数(第14天)
  • QwertyLearner+cpolar:如何远程提升英文输入效率?
  • 【题解】洛谷 P4081 [USACO17DEC] Standing Out from the Herd P [后缀数组 SA]
  • 论测试驱动开发DD
  • QCustomPlot 性能优化与问题排查
  • 建网站要多少钱用自己的服务器手机网站 图标
  • 需求分析:对原始需求进行加工提炼
  • SFT/DPO/PPO/GRPO训练全解析
  • 海康 智能相机二开 绘制底图+测试工具应用框
  • DIY主机无网络安装PVE全记录:手机热点+笔记本网络共享实战
  • 从“氛围编程“到“氛围研究“:OpenAI的GPT-5与未来自动化研究之路
  • 手动编译 OpenCV 4.1.0 源码,生成 ARM64 动态库 (.so),然后在 Petalinux 中打包使用。
  • 乐从做网站wordpress lover主题
  • 品牌型网站制作有哪些公司自建房设计
  • 知微传感Dkam系列3D相机SDK例程篇:CSharp点云滤波
  • AEO 与 SEO 双引擎:整合策略赢得搜索全域可见性
  • 精读C++20设计模式:行为型设计模式:中介者模式
  • 【C++经典例题】逆波兰表达式求值:栈的经典应用与实现详解
  • mmcv 安装 2025
  • 设计模式(C++)详解——观察者模式(Observer)(2)
  • LeetCode 392 判断子序列
  • 树的存储结构
  • 2025年9月GESP(C++三级):数组清零
  • 怎样查看网站建设时间注册公司需要什么费用
  • Deepoc具身模型外拓板:重塑居家服务机器人的交互革命