mybatisplus集成geometry实现增改功能

news2025/1/10 23:31:59

前言

在我们工作中想要实现将空间点位信息存储到数据库时,一般使用以下语句实现

INSERT INTO `test-point` ( point,text ) VALUES ( st_GeomFromText ( 'POINT(1 1)' ),'第1个点');
update `test-point` set point=st_PointFromText('POINT(5 5)') where id =10;

但是这样每次都要去编写新增与编辑的sql语句非常麻烦,体现不出mybatisplus的便捷性,所以可以增加GeometryTypeHandler在mybatisplus生成新增编辑语句时将st_GeomFromText ()函数拼接到sql语句上,更加方便快捷

一.准备工作

  1. 首先项目添加依赖:
<dependency>
    <groupId>com.vividsolutions</groupId>
    <artifactId>jts</artifactId>
    <version>1.13</version>
</dependency>
  1. 在项目中加入GeometryTypeHandler
package com.sinosoft.springbootplus.lft.business.dispatch.map.common;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.io.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

@MappedTypes({String.class})
@MappedJdbcTypes({JdbcType.OTHER})
@Slf4j
public class GeometryTypeHandler extends BaseTypeHandler<String> {


	@Override
	public void setNonNullParameter(PreparedStatement preparedStatement, int i, String s, JdbcType jdbcType) throws SQLException {
			try{
				//String转Geometry
				Geometry geo = new WKTReader(new GeometryFactory(new PrecisionModel())).read(s);
				// Geometry转WKB
				byte[] geometryBytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN, false).write(geo);
				// 设置SRID为mysql默认的 0
				byte[] wkb = new byte[geometryBytes.length+4];
				wkb[0] = wkb[1] = wkb[2] = wkb[3] = 0;
				System.arraycopy(geometryBytes, 0, wkb, 4, geometryBytes.length);
				preparedStatement.setBytes(i,wkb);
			}catch (ParseException e){
				log.error("坐标转换异常:【{}】",e.getMessage(),e);
			}
		}

	@Override
	public String getNullableResult(ResultSet resultSet, String s){
		try(InputStream inputStream = resultSet.getBinaryStream(s)){
			Geometry geo = getGeometryFromInputStream(inputStream);
			if(geo != null){
				return geo.toString();
			}
		}catch(Exception e){
			log.error("坐标转换异常:【{}】",e.getMessage(),e);
		}
		return null;
	}

	@Override
	public String getNullableResult(ResultSet resultSet, int i){
		try(InputStream inputStream = resultSet.getBinaryStream(i)){
			Geometry geo = getGeometryFromInputStream(inputStream);
			if(geo != null){
				return geo.toString();
			}
		}catch(Exception e){
			log.error("坐标转换异常:【{}】",e.getMessage(),e);
		}
		return null;
	}

	@Override
	public String getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
		return "";
	}
	/**
	 * 流 转 geometry
	 * */
	private  Geometry getGeometryFromInputStream(InputStream inputStream) throws Exception {

		Geometry dbGeometry = null;

		if (inputStream != null) {
			// 二进制流转成字节数组
			byte[] buffer = new byte[255];

			int bytesRead;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while ((bytesRead = inputStream.read(buffer)) != -1) {
				baos.write(buffer, 0, bytesRead);
			}
			// 得到字节数组
			byte[] geometryAsBytes = baos.toByteArray();
			// 字节数组小于5 异常
			if (geometryAsBytes.length < 5) {
				throw new RuntimeException("坐标异常");
			}

			//字节数组前4个字节表示srid 去掉
			byte[] sridBytes = new byte[4];
			System.arraycopy(geometryAsBytes, 0, sridBytes, 0, 4);
			boolean bigEndian = (geometryAsBytes[4] == 0x00);
			// 解析srid
			int srid = 0;
			if (bigEndian) {
				for (byte sridByte : sridBytes) {
					srid = (srid << 8) + (sridByte & 0xff);
				}
			} else {
				for (int i = 0; i < sridBytes.length; i++) {
					srid += (sridBytes[i] & 0xff) << (8 * i);
				}
			}

			WKBReader wkbReader = new WKBReader();
			// WKBReader 把字节数组转成geometry对象。
			byte[] wkb = new byte[geometryAsBytes.length - 4];
			System.arraycopy(geometryAsBytes, 4, wkb, 0, wkb.length);
			dbGeometry = wkbReader.read(wkb);
			dbGeometry.setSRID(srid);
		}
		return dbGeometry;
	}
}

二.使用

找到相对应的空间点位字段,加上注解:

@TableField(typeHandler = GeometryTypeHandler.class)
如下图
在这里插入图片描述
这样的话正常传入字段内容point(1 2),在新增和编辑时mybatisplus就会自动拼接st_GeomFromText (),实现空间点位数据的录入和编辑了.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/835981.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

介绍个小工具 - ABAP Cleaner

1. 背景 在编写ABAP代码时&#xff0c;我们可以通过Pretty Printer &#xff08;Shift F1&#xff09;去完成代码的美化&#xff0c;但Pretty Printer所能提供的仅仅是关键字大小写的设置、以及行首留空格的控制&#xff0c;如下图所示。 也就是说&#xff0c;Pretty Printer…

【MySQL】仓储--维护出入库流水、库存,去重数量逻辑修正

系列文章 C#底层库–MySQLBuilder脚本构建类&#xff08;select、insert、update、in、带条件的SQL自动生成&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类&#xff08;推荐阅读&#xff0…

【QNX】快速入门指南

目录 1.QNX 快速入门指南 2.系统要求 2.安装 QNX Momentics 开发套件 3.安装 QNX Neutrino 实时操作系统 4.QNX Neutrino 操作系统的联网 1.QNX 快速入门指南 本指南旨在帮助用户安装和配置 QNX Momentics 工具与 QNX Neutrino 操作系统&#xff0c;以便用户立即进行程序开…

Mybatis 实体类属性名和表中字段名不一致怎么处理

一. 前言 最近耀哥有学生出去面试&#xff0c;被问到 “Mybatis实体类的属性名和表中的字段名不一致该怎么处理&#xff1f;”&#xff0c;这其实是一个很经典的面试题&#xff0c;接下来耀哥就为大家详细解析一下这道面试题。 二. 分析 2.1 实体类和字段名不一致所带来的后果…

<C/C++>日期和时间的使用(time相关函数大全)

1、函数详解及示例 1- time_t time(time_t *time); 1&#xff09;功能&#xff1a;获取或设置系统时间。 2&#xff09;参数&#xff1a;若给定参数&#xff0c;则将当前时间保存到该参数中&#xff1b;若不给定参数&#xff0c;参数填NULL。 3&#xff09;返回值&#xff1…

CANDela Cdd 文件和CddT文件的相互转化

cdd转cddT Step1 点击Check Consistency , step2 没有任何error step1 选择Convert Document to Template , 然后选择想要转换的文件 保存cddt文件 cddT转cdd cddt文件的可编辑权限更高&#xff0c;但是在diva工程和canoe中只能使用cdd文件&#xff0c;所以&#xff0c;我们…

跑步用哪款耳机比较好、最适合跑步用的蓝牙耳机推荐

运动时聆听音乐可以为枯燥的过程带来娱乐&#xff0c;并且能够转移注意力&#xff0c;让人忽略身体负荷带来的不适感。而一款出色的运动耳机则成为锻炼过程中的重要辅助&#xff0c;它能够帮助控制节奏&#xff0c;使运动过程更加愉悦和高效。以下是一些备受推崇的热门运动耳机…

EventBus 开源库学习(一)

一、概念 EventBus是一款在 Android 开发中使用的发布-订阅事件总线框架&#xff0c;基于观察者模式&#xff0c;将事件的接收者和发送者解耦&#xff0c;简化了组件之间的通信&#xff0c;使用简单、效率高、体积小。 一句话&#xff1a;用于Android组件间通信的。 二、原理…

Windows环境下VSCode安装PlatformIO Cero报错ERROR: HTTP error 403 while getting

安装PlatformIO插件成功&#xff0c;初始化失败 错误信息判断问题尝试访问https://pypi.tuna.tsinghua.edu.cn/simple/platformio/成功点击文件后报错如下&#xff1a; 解决问题- 换源 &#xff08; Windows下有两个地方需要更改&#xff09;cmd命令行Pip文件 总结&#xff1a;…

C语言指针操作数组赋值

1、通过指针修改数组元素的值 ps:int a[10] {10}; 数组名a &a[0] a1 &a[0]1 跨过得是数组元素类型的长度&#xff0c;&a是对整个数组取地址&#xff0c;&a1是跨过整个数组的长度 #include "stdio.h" #include <stdlib.h>int main() {i…

LeetCode-654-最大二叉树

一&#xff1a;题目描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。递归地在最大值 左边 的 子数组前缀上 构建左子树。递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回…

勒索软件攻击防御的9件事

什么是勒索软件攻击&#xff1f; 勒索软件是一种特定类型的恶意软件&#xff0c;它将数据作为“人质”来勒索赎金。网络钓鱼电子邮件是其一种常见的传播方式&#xff0c;同时勒索软件也可以借由下载广泛传播&#xff0c;也就是在用户访问受到感染的网站时进行传播。随着网络攻…

推荐GitHub 中的 C avl tree

https://github.com/greensky00/avltree.git 6 内核果然是,最好的C 标准库 &#x1f602;, 早晚手撕一遍这个代码

大模型,拼算力更拼落地力

近年来&#xff0c;随着人工智能领域的快速发展&#xff0c;大模型已经成为了业界热议的话题之一。在这个信息爆炸的时代&#xff0c;数据变得比以往任何时候都更加丰富&#xff0c;而大模型的兴起&#xff0c;为我们揭示了探索数据中蕴藏的价值和智慧提供了全新的途径。然而&a…

【阵列信号处理】空间匹配滤波器、锥形/非锥形最佳波束成形器、样本矩阵反演 (SMI) 研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Unity Shader编辑器工具类ShaderUtil 常用函数和用法

Unity Shader编辑器工具类ShaderUtil 常用函数和用法 Unity的Shader编辑器工具类ShaderUtil提供了一系列函数&#xff0c;用于编译、导入和管理着色器。本文将介绍ShaderUtil类中的常用函数和用法。 编译和导入函数 CompileShader 函数签名&#xff1a;public static bool C…

发灰黑行业用搜索留痕排名推广哪款软件好

发灰黑行业用搜索留痕排名推广哪款软件好 最近微博视频排名发不了&#xff0c;不收录 目前推荐泛目录或者寄生虫 以后只要知道这个逻辑就可以 平台会因为发的人多而和谐&#xff0c;也就是发不出去 接下来给大家介绍下 想要网站排名&#xff0c;却又不知道具体的优化步骤和方…

自建类ChatGPT服务:本地化部署与远程访问教程

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

基于注解实现接口幂等机制防止数据重复提交

1:什么是接口幂等性? 能解决什么问题? 接口幂等性是指无论调用接口的次数是一次还是多次&#xff0c;对于同一资源的操作都只会产生相同的效果。 比如: 一个订单记账的时候,会同步扣减库存数量,如果记账的按钮被用户多次触发,就会导致一个订单库存却被多次扣减的情况. 如果对…

【ArcGIS Pro二次开发】(56):界址点导出Excel

界址点成果表是地籍测绘中的一种表格&#xff0c;用于记录地块的界址点坐标和相关属性信息。 这个工具的目的就是为了将地块要素导出为界址点成果表。 一、要实现的功能 如上图所示&#xff0c;在【数据处理】组—【Excel相关】面板下&#xff0c;点击【界址点导出Excel】工具。…