GeoServer使用MySQL数据库出现“Error decoding wkb”错误的一种情况

news2024/11/15 8:10:28

错误

请看一下GeoServer官方文档的警告

Warning:Currently the MySQL extension is unmaintained and carries unsupported status. While still usable, do not expect the same reliability as with other extensions.

没事不要特立独行使用MySQL当GeoServer的空间数据库,会变得不幸,而且不知道为什么会不幸。就比如我标题遇到的错误,一样的系统、数据库版本、一样的数据库名、一样的编码和排序、一样的表名,一样的字段,一样的数据,一份数据工作正常,一份数据会出现这个错误。

渲染界面报错:
在这里插入图片描述

后台错误详情:

ERROR [renderer.lite] - java.io.IOException: Error decoding wkb
java.lang.RuntimeException: java.io.IOException: Error decoding wkb
	at org.geotools.jdbc.JDBCFeatureReader.readNextFeature(JDBCFeatureReader.java:389)
	at org.geotools.jdbc.JDBCFeatureReader.hasNext(JDBCFeatureReader.java:332)
	at org.geotools.data.store.ContentFeatureCollection$WrappingFeatureIterator.hasNext(ContentFeatureCollection.java:141)
	at org.geoserver.feature.RetypingFeatureCollection$RetypingIterator.hasNext(RetypingFeatureCollection.java:112)
	at org.geotools.data.crs.ForceCoordinateSystemIterator.hasNext(ForceCoordinateSystemIterator.java:121)
	at org.geotools.renderer.lite.StreamingRenderer.drawPlain(StreamingRenderer.java:2664)
	at org.geotools.renderer.lite.StreamingRenderer.processStylers(StreamingRenderer.java:2286)
	at org.geotools.renderer.lite.StreamingRenderer.paint(StreamingRenderer.java:917)
	at org.geoserver.wms.map.RenderedImageMapOutputFormat.produceMap(RenderedImageMapOutputFormat.java:540)
	at org.geoserver.wms.map.RenderedImageMapOutputFormat.produceMap(RenderedImageMapOutputFormat.java:202)
	at org.geoserver.wms.map.RenderedImageMapOutputFormat.produceMap(RenderedImageMapOutputFormat.java:82)
	at org.geoserver.wms.GetMap.executeInternal(GetMap.java:344)
	at org.geoserver.wms.GetMap.run(GetMap.java:203)
	at org.geoserver.wms.GetMap.run(GetMap.java:113)
	at org.geoserver.wms.DefaultWebMapService.getMap(DefaultWebMapService.java:250)
	...
Caused by: java.io.IOException: Error decoding wkb
	at org.geotools.data.mysql.MySQLDialectBasic.decodeGeometryValue(MySQLDialectBasic.java:222)
	at org.geotools.jdbc.SQLDialect.decodeGeometryValue(SQLDialect.java:764)
	at org.geotools.jdbc.JDBCFeatureReader.readNextFeature(JDBCFeatureReader.java:381)
	... 153 more
Caused by: org.locationtech.jts.io.ParseException: Attempt to read past end of input
	at org.locationtech.jts.io.ByteOrderDataInStream.read(ByteOrderDataInStream.java:142)
	at org.locationtech.jts.io.ByteOrderDataInStream.readInt(ByteOrderDataInStream.java:107)
	at org.locationtech.jts.io.WKBReader.readGeometry(WKBReader.java:229)
	at org.locationtech.jts.io.WKBReader.read(WKBReader.java:191)
	at org.locationtech.jts.io.WKBReader.read(WKBReader.java:159)
	at org.geotools.data.mysql.MySQLDialectBasic.decodeGeometryValue(MySQLDialectBasic.java:219)
	... 155 more

GeoServer使用MySQL

GeoServer默认是不支持MySQL的,需要安装相应的扩展组件才支持。比起根据官方文档中 Installing the MySQL extension的指引下载MySQL扩展组件,我更推荐到GeoTools官网下载对应版本的包,然后把其中的gt-jdbc-mysql-x.x.jarmysql-connector-java-x.x.x.jar复制到geoserver/webapps/geoserver/WEB-INF/lib文件夹下,如果重启GeoServer之后可以添加MySQL数据源,发布图层、正常预览,那么恭喜,不需要往下看了,如果遇到我一样的错误,就很不幸,需要了解一点点Java开发才能解决问题。

解决方法

GeoTools是一个开源的Java 空间数据操作库,GeoServer里大量使用了GeoTools的库,虽然也没法调试吧,但是通过改代码替换包的形式,一点点追溯下来,最后发现不知道什么原因,他在读MySQL的时候会重复读取主键,比如主键是ID,那他读出来的字段列表会是ID,ID,filed1,the_geom。理论上the_geom的index是3(从1开始算),但有两列ID之后,用index=3读出来的会是field1字段,就导致读出来的并不是空间数据,强行解析成空间数据的时候就会出错,所以就会报错Error decoding wkb

知道了原因,解决起来就简单了,在gt-jdbc这个包里HeuristicPrimaryKeyFinder.java文件的createPrimaryKey方法,加入如下代码,在构造主键时遇到重复的就跳过就可以了:

Boolean exist = false;
for (int i = 0; i < cols.size(); i++) {
	if (cols.get(i).name.equals(columnName)) {
		exist = true;
		break;
	}
}

if (exist) {
	continue;
}

加了之后的createPrimaryKey方法完整代码:

/*
 * Creates a key from a primary key or unique index.
 */
PrimaryKey createPrimaryKey(
		JDBCDataStore store,
		ResultSet index,
		DatabaseMetaData metaData,
		String databaseSchema,
		String tableName,
		Connection cx)
		throws SQLException {
	ArrayList<PrimaryKeyColumn> cols = new ArrayList<>();
	while (index.next()) {
		String columnName = index.getString("COLUMN_NAME");
		// work around. For some reason the first record returned is always 'empty'
		// this was tested on Oracle and Postgres databases
		if (columnName == null) {
			continue;
		}

		// Alter By ZXHM
		Boolean exist = false;
		for (int i = 0; i < cols.size(); i++) {
			if (cols.get(i).name.equals(columnName)) {
				exist = true;
				break;
			}
		}
		if (exist) {
			continue;
		}

		// look up the type ( should only be one row )
		ResultSet columns =
				metaData.getColumns(
						null,
						store.escapeNamePattern(metaData, databaseSchema),
						store.escapeNamePattern(metaData, tableName),
						store.escapeNamePattern(metaData, columnName));
		Class columnType;
		try {
			columns.next();
			columnType = store.getSQLDialect().getMapping(columns, cx);
			if (columnType == null) {
				int binding = columns.getInt("DATA_TYPE");
				columnType = store.getMapping(binding);
				if (columnType == null) {
					LOGGER.warning("No class for sql type " + binding);
					columnType = Object.class;
				}
			}
		} finally {
			store.closeSafe(columns);
		}

		// determine which type of primary key we have
		PrimaryKeyColumn col = null;

		// 1. Auto Incrementing?
		Statement st = cx.createStatement();
		try {
			// not actually going to get data
			st.setFetchSize(1);

			StringBuffer sql = new StringBuffer();
			sql.append("SELECT ");
			store.getSQLDialect().encodeColumnName(null, columnName, sql);
			sql.append(" FROM ");
			store.encodeTableName(tableName, sql, null);
			sql.append(" WHERE 0=1");
			LOGGER.log(Level.FINE, "Grabbing table pk metadata: {0}", sql);

			ResultSet rs = st.executeQuery(sql.toString());
			try {
				if (rs.getMetaData().isAutoIncrement(1)) {
					col = new AutoGeneratedPrimaryKeyColumn(columnName, columnType);
				}
			} finally {
				store.closeSafe(rs);
			}
		} finally {
			store.closeSafe(st);
		}

		// 2. Has a sequence?
		if (col == null) {
			try {
				String sequenceName =
						store.getSQLDialect()
								.getSequenceForColumn(
										databaseSchema, tableName, columnName, cx);
				if (sequenceName != null) {
					col = new SequencedPrimaryKeyColumn(columnName, columnType, sequenceName);
				}
			} catch (Exception e) {
				// log the exception , and continue on
				LOGGER.log(
						Level.WARNING,
						"Error occured determining sequence for "
								+ columnName
								+ ", "
								+ tableName,
						e);
			}
		}

		if (col == null) {
			col = new NonIncrementingPrimaryKeyColumn(columnName, columnType);
		}
		cols.add(col);
	}

	if (!cols.isEmpty()) {
		return new PrimaryKey(tableName, cols);
	}
	return null;
}

我只是稍微了解一点Java,不知道我这个避免重复主键的写法有没有啥问题,现在就是能用就行。最后自己打包替换掉原有的gt-jdbc-x.x.jar然后重启GeoServer就可以了。当然这仅仅只是我遇到的情况,不保证使用MySQL数据库发生Error decoding wkb的报错都是这个情况。总而言之,不到万不得已,不要用MySQL作为GeoServer的空间数据库。

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

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

相关文章

文件和用户管理

Linux基础 提示&#xff1a;个人学习总结&#xff0c;仅供参考。 一、Linux系统部署 二、服务器初始化 三、文件和用户管理 提示&#xff1a;文档陆续更新整理 文件和用户管理 Linux基础一、Linux目录结构二、文件管理1.文件类型2.文件管理命令 三、用户管理1. 用户/组基本概…

MySQL隐式类型转换

当运算符与不同类型的操作数一起使用时&#xff0c;会发生类型转换以使操作数兼容。有些转换是隐式发生的。例如&#xff0c;MySQL会根据需要自动将字符串转换为数字&#xff0c;反之亦然。 转换规则 如果一个或两个参数都为NULL&#xff0c;则比较结果为NULL 。但是相等比较…

Android Wifi 扫描

今天拿了个新需求&#xff0c;要求为工厂开发一个扫地机模组检测功能的App&#xff0c;需求逻辑&#xff1a; 1.可以选择机器支持的WBR3 模组和WR3 模组&#xff1b; 2.可以选择机器热点名称的前缀&#xff1a;Thamtu 和 SmartLife&#xff0c;还有自定义输入前缀&#xff1b…

Java概述

Java语言简史&#xff1a; 是SUN(Stanford University Network&#xff0c;斯坦福大学网络公司 ) 1995年推出的一门高级编程语言。 是一种面向Internet的编程语言。Java一开始富有吸引力是因为Java程序可以在Web浏览器中运行。这些Java程序被称为Java小程序&#xff08;applet&…

foldersync使用感受

foldersync简介 ​ FolderSync pro是一款功能非常强大的设备本地存储(包括SD卡)文件/文件夹与云存储同步应用。它可以将手机中的文件自动同步到云端空间&#xff0c;支持包括 FTP、WebDAV、Dropbox、 Google Docs 在内的众多空间。 FolderSync Pro 支持各种不同的云服务商和文件…

CTA策略趋势类

趋势策略 趋势策略日内策略Hilbert 策略R-Braker 策略Dual Thrust 策略菲阿里四价策略空中花园策略 日间策略移动平均线MACD 策略Aberration 策略ATR 策略动量策略肯特纳通道自动识别趋势的追涨交易策略 趋势策略 市场只有两种状态&#xff1a;震荡和单边。 而两种市场状态只…

springboot项目:瑞吉外卖 前后端详细分析 part4

part 1 part 2 part 3 part 4 本页 文章目录 5 套餐管理5.1 新增套餐5.1.1 整体分析5.1.2 前端分析5.1.3 后端分析 持续更新中 5 套餐管理 5.1 新增套餐 5.2 套餐信息分页查询 5.3 删除套餐 其他小功能都比较简单且类似&#xff0c;不再赘述 5.1 新增套餐 5.1.1 整体分析 套…

jmeter取样器javaRequest脚本8

1,创建一个maven工程2,通过maven编译打包生成一个jar包3,重启jmeter&#xff0c;新建java request请求4,开始执行脚本本文永久更新地址: 1,创建一个maven工程 在pom.xml文件中添加 maven下载地址&#xff1a;https://mvnrepository.com/artifact/org.apache.jmeter/ApacheJMe…

【MySQL】关于 SQL 语句执行分析的二三事

一、为什么要发生这件事 确实&#xff0c; 平时我们增删改查写的好好的&#xff0c; 各种业务代码&#xff0c;各种小接口写的不亦乐乎&#xff0c;正常是没时间干这个的&#xff0c;但是但是&#xff0c;这不是还有点技术追求嘛&#xff0c;假如我们平时测一个小接口&#xf…

【LeetCode】199.二叉树的右视图

1.问题 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 示例 1: 输入: [1,2,3,null,5,null,4] 输出: [1,3,4] 示例 2: 输入: [1,null,3] 输出: [1,3] 示例 3: 输入: [] 输出: []…

类加载过程

基本说明 反射机制是Java实现动态语言的关键&#xff0c;也就是通过反射实现类动态加载。 静态加载&#xff1a;编译时加载相关的类&#xff0c;如果没有则报错&#xff0c;依赖性太强动态加载&#xff1a;运行时加载需要的类&#xff0c;如果运行时不用该类&#xff0c;即使…

C++关于线程的一些操作

线程创建和接收 std::this_thread::get_id()获取当前线程的线程ID std::this_thread::yield()让步结束当前线程的时间片 int main() {vector<thread> threads(2);threads[0] thread([]() {cout << this_thread::get_id() << endl;});threads[1] thread([](…

Baumer工业相机中偏振相机如何使用Baumer堡盟GAPI SDK来进行偏振数据的计算转换输出(C#)

项目场景 Baumer工业相机堡盟相机是一种高性能、高质量的工业相机&#xff0c;可用于各种应用场景&#xff0c;如物体检测、计数和识别、运动分析和图像处理。 Baumer的万兆网相机拥有出色的图像处理性能&#xff0c;可以实时传输高分辨率图像。此外&#xff0c;该相机还具…

ansible自动运维——ansible使用临时命令通过模块来执行任务

大家好&#xff0c;这里是天亮之前ict&#xff0c;本人网络工程大三在读小学生&#xff0c;拥有锐捷的ie和红帽的ce认证。每天更新一个linux进阶的小知识&#xff0c;希望能提高自己的技术的同时&#xff0c;也可以帮助到大家 另外其它专栏请关注&#xff1a; 锐捷数通实验&…

【机器学习实战】Python基于SVD奇异值分解进行矩阵分解(八)

文章目录 1 前言1.1 奇异值分解1.2 奇异值分解的应用 2 简单计算SVD2.1 NumPy 计算 SVD2.2 scikit-learn 计算截断 SVD2.3 scikit-learn 计算随机 SVD 3 demo数据演示3.1 导入函数3.2 导入数据3.3 计算SVD 4 讨论 1 前言 1.1 奇异值分解 奇异值分解&#xff08;Singular Valu…

信息安全复习四:置换密码乘积密码隐写术

一、章节梗概 置换密码、Rail Fence密码、行置换密码、乘积密码、转子机、隐写术 二、置换技术 2.1 定义 重新排列明文字母&#xff0c;达到信息加密的目的。 与替代密码不同的是&#xff0c;原来明文中的字母同样出现在密文中&#xff0c;只是顺序被打断。 古典的置换密码…

.net6 core Worker Service项目发布部署到Linux,以守护进程服务的形式部署启动

一、发布项目 1、以文件夹形式 2、目标运行时选对应的平台&#xff08;Linux-x64&#xff09; 3、文件夹选项&#xff1a;在发布前删除所有现有文件 二、部署项目&#xff08;安装.net6环境&#xff1a;参考Linux安装 dotnet sdk 6.0&#xff09; &#xff08;1&#xff09;…

《Spring MVC》 第二章 让程序run起来

前言 Spring MVC 是 Spring 框架提供的一款基于 MVC 模式的轻量级 Web 开发框架。 Spring MVC 本质是对 Servlet 的进一步封装&#xff0c;其最核心的组件是DispatcherServlet&#xff0c;它是 Spring MVC 的前端控制器&#xff0c;主要负责对请求和响应的统一地处理和分发。C…

用好Python自然语言工具包-- 实例“基于本地知识库的自动问答”

首先鸣谢thomas-yanxin 本问中示例来自他在GitHub上的开源项目“基于本地知识库的自动问答”&#xff0c;链接如下&#xff1a; thomas-yanxin/LangChain-ChatGLM-Webui: 基于LangChain和ChatGLM-6B的针对本地知识库的自动问答 (github.com) 目录 1. 基础知识&#xff1a; …

JVM调优最佳参数

项目背景 C端的项目&#xff0c;用户量比较多&#xff0c;请求比较多。 启动参数表 Xmx指定应用程序可用的最大堆大小。 Xms指定应用程序可用的最小堆大小。 &#xff08;一般情况下&#xff0c;需要设置Xmx和Xms为相等的值&#xff0c;且为一个固定的值&#xff09; 如果该值…