升级H2数据库2.x版本遇见的问题

news2024/9/29 1:21:01

目录

    • 一、引言
    • 二、集成H2基础配置
    • 三、升级H2版本2.x遇到的问题
        • 报错1
        • 报错2
    • 三、H2关键字

一、引言

之前在跑代码单元测试时,一直用的内存数据库H2代替实际的Mysql数据库,如此便省去了对Dao的大量mock代码,类似于在跑Junit单元测试时直接跑了集成测试。但是H2的语法和Mysql还是有细微差别的,可使用Mysql兼容模式,实际测试时除了个别Mysql的函数如FIND_IN_SET等不支持,其他基本的SQL语句都还是支持的。

注:
H2兼容的数据库模式包括:Mysql、MariaDB、PostgreSQL、Oracle、MS SQL、HSQLDB、DB2、Derby,
具体说明参见:http://h2database.com/html/features.html#compatibility

二、集成H2基础配置

Spring JUnit集成H2代替Mysql的相关配置如下:
maven依赖:

<properties>  
	<!-- 后续会介绍升级到2.0.206版本 -->  
    <h2.version>1.4.200</h2.version>      
</properties>
    
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>${h2.version}</version>
    <scope>test</scope>
</dependency>

application-test.yaml配置:

spring:
  # Sql初始化配置
  sql:
    init:
      # 导入h2 table定义
      schema-locations: classpath:h2/demo-schema.sql
      # 导入h2 数据定义
      data-locations: classpath:h2/demo-data.sql
  # 数据库配置
  datasource:
    type: com.zaxxer.hikari.HikariDataSource
    # ============================================================
    # ============= 使用H2内存数据库 ================================
    # ============================================================
    driver-class-name: org.h2.Driver
    # 使用h2内存数据(以mysql兼容模式运行)
    url: jdbc:h2:mem:rbac;MODE=MySQL;DATABASE_TO_LOWER=TRUE
    username: root
    password: 123456

在跑单元测试时,可通过@ActiveProfiles(“test”)激活application-test.yaml配置:

@ActiveProfiles("test")
@SpringBootTest
public class MyBaseTest {

	@BeforeEach
	void setUp() {
		...
	}
	
}

---

@ActiveProfiles("test")
@SpringBootTest
public class MyAppTest extends MyBaseTest {

	@Test
	void testMyFunc() {
		...
	}

}

配置spring.sql.init.schema-locations | data-locations对应的即为H2内存数据库的schema定义(table定义)和数据,
以上配置中的h2/demo-schema.sql、h2/demo-data.sql可通过Idea插件Mysql-to-H2将原始的Mysql语句转换为H2 Sql语句,以避免Sql语法不兼容.
在这里插入图片描述

三、升级H2版本2.x遇到的问题

测试用例在H2版本1.4.200时运行都没有问题,后续将H2版本升级为2.x版本(2.0.206):

<properties>  
    <h2.version>2.0.206</h2.version>      
</properties>
    
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>${h2.version}</version>
    <scope>test</scope>
</dependency>

升级后同样的代码运行后出现以下异常:

报错1

Cause: org.h2.jdbc.JdbcSQLSyntaxErrorException: 
Syntax error in SQL statement "SELECT\000a         \000a        DD.ID AS ID,\000a        DD.DICT_DETAIL_CODE AS VALUE[*],\000a        DD.DICT_DETAIL_NAME AS NAME,\000a        DD.PARENT_CODE AS PARENT_ID,\000a        DD.DICT_TYPE_CODE AS TYPE\000a     \000a        FROM SYSTEM_DICT_DETAIL DD"; \
expected "identifier"; SQL statement:
select
         
        dd.id as id,
        dd.dict_detail_code as value,
        dd.dict_detail_name as name,
        dd.parent_code as parent_id,
        dd.dict_type_code as type
     
        from system_dict_detail dd [42001-206]

该测试用例对应Mybatis Mapper XML中的SQL语句为:

select
dd.id as id,
dd.dict_detail_code as value,
dd.dict_detail_name as name,
dd.parent_code as parent_id,
dd.dict_type_code as type
from system_dict_detail dd

注意上述异常中的关键词expected "identifier";,查询了 Github/h2/issues/3363后发现:

  • H2的2.x版本要求对保留的关键字使用双引号包围
  • 又或者可通过jdbc url上的;NON_KEYWORDS=KEYWORD1,KEYWORD2格式对指定保留关键字进行排除
    在这里插入图片描述

上述SQL语句出问题的地方就是使用了保留关键字value,所以才出现了expected "identifier";异常,

select
...
-- 注意as后面的value,此value与H2关键字冲突
dd.dict_detail_code as value,
...

可通过双引号包围关键字的方式避免报错,修改后Sql语句如下:

select
...
-- 注意as后面的h2关键字value,可使用英文双引号包围"value"
dd.dict_detail_code as "value",
...

注:
上述sql语句本身使用关键字(如value)作为列名就有问题,实际开发时不推荐此种方式。

报错2

异常和 报错1 类似,也包含expected "identifier";提示,具体对应的Mybatis Mapper XML中的SQL语句为:

select
u.id,
u.name,
...
from system_user u
...

比较坑的是Sql语句中的表名system_user在H2中也是保留关键字,
起初直接使用双引号包围表名"system_user",修改如下:

select
...
from "system_user" u
...

此种方式在H2中运行没问题,但是在Mysql中表名使用双引号包围 运行时报语法错误。

最终使用了在jdbc url上添加;NON_KEYWORDS=SYSTEM_USER对关键字system_user进行排除的方式,即解决了H2报错的问题,也保证了原语句在Mysql中的执行,具体jdbc url配置如下:

spring: 
  datasource:
    url: "jdbc:h2:mem:rbac;MODE=MySQL;DATABASE_TO_LOWER=TRUE;NON_KEYWORDS=SYSTEM_USER"

三、H2关键字

H2保留的Keyword具体说明参见:https://h2database.com/html/advanced.html#keywords

KeywordH2SQL Standard
2016201120082003199992
ALL+++++++
AND+++++++
ANY+++++++
ARRAY++++++
AS+++++++
ASYMMETRIC+++++NR
AUTHORIZATION+++++++
BETWEEN+++++NR+
BOTHCS++++++
CASE+++++++
CAST+++++++
CHECK+++++++
CONSTRAINT+++++++
CROSS+++++++
CURRENT_CATALOG++++
CURRENT_DATE+++++++
CURRENT_PATH++++++
CURRENT_ROLE++++++
CURRENT_SCHEMA++++
CURRENT_TIME+++++++
CURRENT_TIMESTAMP+++++++
CURRENT_USER+++++++
DAY+++++++
DEFAULT+++++++
DISTINCT+++++++
ELSE+++++++
END+++++++
EXCEPT+++++++
EXISTS+++++NR+
FALSE+++++++
FETCH+++++++
FOR+++++++
FOREIGN+++++++
FROM+++++++
FULL+++++++
GROUP+++++++
GROUPSCS++
HAVING+++++++
HOUR+++++++
IF+
ILIKECS
IN+++++++
INNER+++++++
INTERSECT+++++++
INTERVAL+++++++
IS+++++++
JOIN+++++++
KEY+NRNRNRNR++
LEADINGCS++++++
LEFT+++++++
LIKE+++++++
LIMITMS+
LOCALTIME++++++
LOCALTIMESTAMP++++++
MINUSMS
MINUTE+++++++
MONTH+++++++
NATURAL+++++++
NOT+++++++
NULL+++++++
OFFSET++++
ON+++++++
OR+++++++
ORDER+++++++
OVERCS++++
PARTITIONCS++++
PRIMARY+++++++
QUALIFY+
RANGECS++++
REGEXPCS
RIGHT+++++++
ROW++++++
ROWNUM+
ROWSCS++++++
SECOND+++++++
SELECT+++++++
SESSION_USER++++++
SET+++++++
SOME+++++++
SYMMETRIC+++++NR
SYSTEM_USER+++++++
TABLE+++++++
TO+++++++
TOPMS
CS
TRAILINGCS++++++
TRUE+++++++
UESCAPE+++++
UNION+++++++
UNIQUE+++++++
UNKNOWN+++++++
USER+++++++
USING+++++++
VALUE+++++++
VALUES+++++++
WHEN+++++++
WHERE+++++++
WINDOW+++++
WITH+++++++
YEAR+++++++
_ROWID_+

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

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

相关文章

报错:crbug/1173575 non-js module files deprecated

文章目录 报错分析解决方法一&#xff1a;尽可能使用JS模块文件方法二&#xff1a;使用type"module"属性方法三&#xff1a;忽略警告 报错 分析 这个错误报告 (crbug/1173575) 指的是非 JavaScript 模块文件将不再被支持&#xff0c;并且已经弃用。这个问题是因为Ch…

【获奖案例巡展】信创先锋之星——云上贵州信创工程中心大数据中台

为表彰使用大数据、人工智能等基础软件为企业、行业或世界做出杰出贡献和巨大创新的标杆项目&#xff0c;星环科技自2021年推出了“新科技 星力量” 星环科技科技实践案例评选活动&#xff0c;旨在为各行业提供更多的优秀产品案例&#xff0c;彰显技术改变世界的力量&#xff0…

【ctfshow】命令执行->web29-web44

前言 半夜网抑云听歌听emo了 z 刷会儿题不然睡不着了呜呜呜 红中(hong_zh0) CSDN内容合伙人、2023年新星计划web安全方向导师、 华为MindSpore截至目前最年轻的优秀开发者、IK&N战队队长、 吉林师范大学网安大一的一名普通学生、搞网安论文拿了回大挑校二、 阿里云专家博…

2023年,人工智能和数据训练呈现哪些新趋势?

最近&#xff0c;多才多艺的“全能网友”ChatGPT一次次火出圈。未来人工智能将以多快的速度、发展到何种地步&#xff1f;人们已经开始坐下来认真地探讨和思考。 我们生活在这个日新月异的时代。新的一年&#xff0c;人工智能的真正能力和应用场景又发生了哪些演进&#xff1f;…

【学习笔记】go-gRPC 初尝试

安装protoc 安装地址 找到对应版本的anz安装文件 解压&#xff0c;将文件夹移动到goroot目录中&#xff0c;可以通过命令go env查看goroot目录。 如我的goroot目录为D:\Program Files\Go 或者移动到自定义目录&#xff0c;并将该目录设置到环境变量中即可。 安装go插件 …

混淆矩阵的输出,异常检测可视化(针对二分类)

对于二分类任务&#xff1a; 真阳性&#xff08;True Positives, TP&#xff09;为真实值为1&#xff0c;预测值为1&#xff0c;即正确预测出的正样本个数真阴性&#xff08;True Negatives, TN&#xff09;为真实值为0&#xff0c;预测值为0&#xff0c;即正确预测出的负样本…

网关(史上最全)

什么是网关 网关&#xff0c;很多地方将网关比如成门&#xff0c;没什么问题&#xff0c;但是需要区分网关与网桥的区别。 网桥工作在数据链路层&#xff0c;在不同或相同类型的LAN之间存储并转发数据帧&#xff0c;必要时进行链路层上的协议转换。可连接两个或多个网络&…

漫画:是喜,还是悲?AI竟帮我们把Office破活干完了

图文原创&#xff1a;亲爱的数据 国产大模型烈火制造。阿里百度字节美团各科技大佬不等闲。 大模型嘛&#xff0c;重大工程&#xff0c;对我等“怀保小民”来说&#xff0c;只关心怎么用&#xff0c;不关心怎么造。 我来介绍一下自己&#xff0c;我是一个写稿男团组合的成员&am…

13、fishhook原理Dobby

一、fishhook原理 1.1 fishhook代码分析 int rebind_symbols(struct rebinding rebindings[], size_t rebindings_nel) {//prepend_rebindings的函数会将整个 rebindings 数组添加到 _rebindings_head 这个链表的头部//Fishhook采用链表的方式来存储每一次调用rebind_symbols…

Java动态代理(JDK/CGLIB)静态代理

Java Guide动态代理阅读笔记。 一、代理模式 代理模式是一种比较好的理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real obiect)的访问&#xff0c;这样就可以在不修改原目标对象的前提下&#xff0c;提供额外的功能操作&#xff0c;扩展目标对象的功能。 …

vue2+vue3——36+

vue2vue3——36 尚硅谷vue2vue2 Vue监测数据的原理_数组【18:56】数组vue 查看 没有 set() get()对象 有 get() set() 监测不到 不更新测试 : 数据改了 &#xff0c; 单页面没变 修改数组的 7方法 &#xff1a; filter 不改变原数组&#xff0c; 返回新的 数组 可以替换掉 原数…

逍遥自在学C语言 | 位运算符~的高级用法

前言 在上一篇文章中&#xff0c;我们介绍了^运算符的高级用法&#xff0c;本篇文章&#xff0c;我们将介绍~ 运算符的一些高级用法。 一、人物简介 第一位闪亮登场&#xff0c;有请今后会一直教我们C语言的老师 —— 自在。 第二位上场的是和我们一起学习的小白程序猿 ——…

linux 安装git(centos7)-yum

文章目录 在 Linux 系统上安装 Git步骤一&#xff1a;使用自带软件管理器安装步骤二&#xff1a;检查 Git步骤三&#xff1a;设置git环境变量 在 Linux 系统上安装 Git Git 是一种分布式版本控制系统&#xff0c;适用于处理从小型到非常大型的项目。在 Linux 系统上&#xff0…

c++11 标准模板(STL)(std::queue)(四)

定义于头文件 <queue> template< class T, class Container std::deque<T> > class queue; std::queue 类是容器适配器&#xff0c;它给予程序员队列的功能——尤其是 FIFO &#xff08;先进先出&#xff09;数据结构。 类模板表现为底层容器的包…

flac格式如何转mp3,3招帮你搞定

flac格式如何转mp3&#xff0c;3招帮你搞定的方法来啦。当你的音频是flac格式是不是很头疼&#xff0c;又不知道怎么转mp3 。然后网上搜索出很多方法又不知道从哪个下手&#xff0c;是不是很疑惑&#xff1f;那今天就来看看小编推荐的方法吧&#xff0c;一定让你眼前一亮&#…

petalinux-2021.1在zynq7020的flash上启动linux

一、 前言 在电脑上安装虚拟机或者找一个电脑安装linux&#xff0c;用于编译petalinux工程&#xff1b;安装与vivado对应的petalinux-tool&#xff1b;版本信息&#xff1a; 1&#xff09;linux&#xff1a;ubuntu16.04.06&#xff1b; 2&#xff09;vivado&#xff1a;v2021.…

row_number 和 cte 使用实例:考场监考安排

row_number 和 cte 使用实例&#xff1a;考场监考安排 考场监考安排使用 cte 模拟两个表的原始数据使用 master..spt_values 进行数据填充优先安排时长较长的考试使用 cte 安排第一个需要安排的科目统计老师已有的监考时长尝试使用 cte 递归&#xff0c;进行下一场考试安排&…

网咯通信基础 - 数据交换方式

文章目录 1 概述2 分类2.1 电路交换2.2 报文交换2.3 分组交换 1 概述 2 分类 2.1 电路交换 图示&#xff1a;发送方和接收方用一系列链路直接连通数据传输划分&#xff1a;电路建立、数据传输 和 电路拆除 3 个过程原理&#xff1a;当交换机收到一个呼叫后就会在网络中寻找一…

机器学习之SVM分类器介绍——核函数、SVM分类器的使用

系类文章目录 机器学习算法——KD树算法介绍以及案例介绍 机器学习的一些常见算法介绍【线性回归&#xff0c;岭回归&#xff0c;套索回归&#xff0c;弹性网络】 文章目录 一、SVM支持向量机介绍 1.1、SVM介绍 1.2、几种核函数简介 a、sigmoid核函数 b、非线性SVM与核函…

运行时内存数据区之堆(一)

堆&#xff08;Heap&#xff09; 堆的核心概述 一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。Java堆区在JVM启动的时候即被创建&#xff0c;其空间大小也就确定了。是JVM管理的最大一块内存空间。堆内存的大小是可以调节的。《Java虚拟机规范》规定…