mybatis-plus由mysql改成达梦数据库

前置条件: 达梦数据库设置了大小写敏感,我比较菜,改不动!先这么凑合着用吧;
因为设置了大小写敏感,所以所有的sql语句都要加 引号;

这样是会报错的:
SELECT  remark,createDept,createBy,createTime,updateBy,updateTime  FROM sys_oss_config这样才可以
SELECT  "create_dept", "create_by", "create_time","update_by", "update_time" FROM "sys_oss_config"

所以只需要将表名和字段名都加上引号就行了

第一步添加依赖

     <dependency><groupId>com.dameng</groupId><artifactId>Dm8JdbcDriver18</artifactId><version>8.1.1.49</version></dependency><!-- Druid 数据源 --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.16</version></dependency>

配置文件修改

type: com.alibaba.druid.pool.DruidDataSource
driverClassName: dm.jdbc.driver.DmDriver
url: jdbc:dm://10.10.10.10:5236?schema=RY_VUE5&useUnicode=true&characterEncoding=utf8
username: SYSDBA
password: DmAdmin123

尤其要注意的是 库名 里面不能有横杠 类似这样"RY-VUE5",这就容易出问题;
指定库要用 schema=RY_VUE5

剩下的就在mybatis-plus配置类中添加两个拦截器
一个是针对所有sql ,添加引号 ,一个是对mybatisplus分页sql 改写的

import cn.hutool.core.net.NetUtil;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.DdlApplicationRunner;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ParameterUtils;
import com.baomidou.mybatisplus.extension.ddl.IDdl;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.util.*;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;import java.sql.SQLException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 这俩拦截器要放前面interceptor.addInnerInterceptor(new QuoteAllSqlInterceptor());interceptor.addInnerInterceptor(new DmMultiLevelPaginationInterceptor());return interceptor;}public static class QuoteAllSqlInterceptor implements InnerInterceptor {// 表名匹配正则(不变)private static final Pattern TABLE_PATTERN = Pattern.compile("(FROM|JOIN)\\s+([a-zA-Z0-9_]+(\\.[a-zA-Z0-9_]+)?)",Pattern.CASE_INSENSITIVE);// 优化字段匹配正则:解决末尾字段未被匹配的问题// 新增对SQL末尾字段的支持(允许字段后是空格、逗号或换行)private static final Pattern COLUMN_PATTERN = Pattern.compile("(?<!\\\")\\b([a-zA-Z0-9_]+)\\b(?!\\\")(?!\\s+[A-Za-z0-9_]*\\.)(?=\\s*[,)\\s]|\\s+AS|\\s+IN|\\s+LIKE)",Pattern.CASE_INSENSITIVE);private static final Pattern COLUMN_ALIAS = Pattern.compile("(FROM|JOIN)\\s+[\"`\\w\\.]+\\s+([a-zA-Z0-9_]+)",Pattern.CASE_INSENSITIVE);@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter,RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {processSql(boundSql);}@Overridepublic void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {BoundSql boundSql = ms.getBoundSql(parameter);processSql(boundSql);}@Overridepublic void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {BoundSql boundSql = sh.getBoundSql();processSql(boundSql);}private void processSql(BoundSql boundSql) {PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);String originalSql = mpBs.sql();if (originalSql == null || originalSql.isEmpty()) {return;}// 先处理表名,再处理字段名String sqlWithTables = addQuotesToTables(originalSql);String sqlWithColumns = addQuotesToColumns(sqlWithTables);//  mp 强制更新SQL,确保所有字段被处理mpBs.sql(sqlWithColumns);}// 表名添加引号(不变)private String addQuotesToTables(String sql) {Matcher matcher = TABLE_PATTERN.matcher(sql);StringBuffer sb = new StringBuffer();while (matcher.find()) {String keyword = matcher.group(1);String tableName = matcher.group(2);if (tableName.contains(".")) {String[] parts = tableName.split("\\.");matcher.appendReplacement(sb, keyword + " \"" + parts[0] + "\".\"" + parts[1] + "\"");} else {matcher.appendReplacement(sb, keyword + " \"" + tableName + "\"");}}return matcher.appendTail(sb).toString();}// 字段名添加引号(重点优化)private String addQuotesToColumns(String sql) {Matcher matcher1 = COLUMN_ALIAS.matcher(sql);List<String> aliases = new ArrayList<>();while (matcher1.find()) {aliases.add(matcher1.group(2)); // 捕获组2为别名}Matcher matcher = COLUMN_PATTERN.matcher(sql);StringBuffer sb = new StringBuffer();while (matcher.find()) {String column = matcher.group(1);// 单独打印匹配到的字段,方便调试System.out.println("匹配到字段:" + column);if (isKeyword(column)) {matcher.appendReplacement(sb, column);} else {if (aliases.contains(column)) {System.out.println("别名不加引号:" + column);} else {matcher.appendReplacement(sb, "\"" + column + "\"");}}}String result = matcher.appendTail(sb).toString();// 打印处理后的SQL,确认是否添加引号System.out.println("处理后的SQL:" + result);return result;}// 完善关键字列表(确保不包含实际字段名)private boolean isKeyword(String word) {Set<String> keywords = new HashSet<>(Arrays.asList("SELECT", "FROM", "WHERE", "AND", "OR", "GROUP", "BY", "ORDER", "LIMIT","INSERT", "UPDATE", "DELETE", "SET", "VALUES", "AS", "JOIN", "ON", "NULL","DESC", "ASC", "IN", "LIKE", "BETWEEN", "IS", "NOT", "LEFT","INTO"));return keywords.contains(word.toUpperCase());}@Overridepublic boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {return true;}@Overridepublic boolean willDoUpdate(Executor executor, MappedStatement ms, Object parameter) {return true;}}/*** 达梦数据库分页拦截器(不依赖setPriority方法)*/public static class DmMultiLevelPaginationInterceptor extends PaginationInnerInterceptor {public DmMultiLevelPaginationInterceptor() {super(DbType.DM);}@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter,RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {// 1. 获取分页参数IPage<?> page = ParameterUtils.findPage(parameter).orElse(null);if (page == null || page.getSize() <= 0) {// 无分页参数时执行默认逻辑super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);return;}// 2. 手动构建无歧义的分页SQLString originalSql = boundSql.getSql();String paginationSql = buildMultiLevelPaginationSql(originalSql, page);// 3. 替换原始SQL(关键步骤)PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);mpBs.sql(paginationSql);// 4. 执行父类逻辑,但禁用其分页处理(使用RowBounds.DEFAULT)super.beforeQuery(executor, ms, parameter, RowBounds.DEFAULT, resultHandler, boundSql);}/*** 构建仅两层嵌套的分页SQL,彻底避免ROW_ID重复*/private String buildMultiLevelPaginationSql(String originalSql, IPage<?> page) {long current = page.getCurrent();long size = page.getSize();long offset = (current - 1) * size;// 清除原始SQL中的分号和多余空格originalSql = originalSql.replaceAll(";|\\s+", " ").trim();// 达梦分页核心:仅用两层嵌套,别名绝对唯一return String.format("SELECT * FROM (" +"  SELECT TMP.*, ROWNUM AS RN2 FROM (" +"    SELECT TMP.*, ROWNUM AS RN1 FROM (" +"      %s" +  // 原始查询"    ) TMP WHERE ROWNUM <= %d" +  // 总条数限制:当前页末尾"  ) TMP WHERE RN1 > %d" +       // 偏移量:跳过前几页"  ORDER BY RN1" +               // 保证排序一致性") TMP WHERE ROWNUM <= %d",      // 每页条数限制originalSql, current * size, offset, size);}}
}

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

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

相关文章

设计模式:外观模式 Facade

目录前言问题解决方案结构代码前言 外观是一种结构型设计模式&#xff0c;能为程序库、框架或其他复杂类提供一个简单的接口。 问题 假设你必须在代码中使用某个复杂的库或框架中的众多对象。正常情况下&#xff0c; 你需要负责所有对象的初始化工作、 管理其依赖关系并按正确…

【数据结构初阶】--二叉树(四)

&#x1f525;个人主页&#xff1a;草莓熊Lotso &#x1f3ac;作者简介&#xff1a;C研发方向学习者 &#x1f4d6;个人专栏&#xff1a; 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》 ⭐️人生格言&#xff1a;生活是默默的坚持&#xff0c;毅力是永久的…

三、平面度检测-差值法

方法一: dev_get_window (WindowHandle) *读取3通道彩色融合图 read_image (Image, ./XYZ彩色融合图.tiff) *拆分3个通道 decompose3 (Image, x, y, z) *将3个通道图像转换为3D模型 xyz_to_object_model_3d (x,y, z, ObjectModel3D) *显示动态3D模型 threshold (z, Regions,…

什么是数据编排?数据编排的流程、优势、挑战及工具有哪些?

目录 一、数据编排的定义与概念 1.数据编排的基本含义 2.数据编排与相关概念的区别 3.数据编排的重要性 二、数据编排的流程 1.需求分析&#xff1a; 2.数据源识别与连接&#xff1a; 3.数据抽取&#xff1a; 4.数据转换&#xff1a; 5.数据加载&#xff1a; 6.监控…

【C++算法】82.BFS解决FloodFill算法_被围绕的区域

文章目录题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;题目链接&#xff1a; 130. 被围绕的区域 题目描述&#xff1a; 解法 BFS一层层剥开。 C 算法代码&#xff1a; class Solution {// 定义四个方向的偏移量&#xff1a;右、左、下、上int dx[4] …

商汤发布具身智能平台,让机器人像人一样和现实世界交互

7月27日&#xff0c;在“大爱无疆模塑未来”WAIC 2025大模型论坛上&#xff0c;商汤科技重磅发布「悟能」具身智能平台。「悟能」具身智能平台以商汤具身世界模型为核心引擎&#xff0c;依托商汤大装置提供端侧和云侧算力支持&#xff0c;能够为机器人、智能设备提供强大的感知…

MCP工作原理

在谈MCP原理前&#xff0c;我们先谈谈MCP的技术前身—Function Calling。1.Function Calling技术在FunctionCalling技术出现之前&#xff0c;大语言模型虽然拥有强大的知识储备和语言理解能力&#xff0c;但是只能提供自身数据库已有的信息&#xff0c;无法和外界进行信息交互。…

VSCode手动版本更新

技术背景 使用VSCode的的过程中&#xff0c;如果打开了自动更新功能&#xff0c;每隔一段时间就会有更新提示。为了保持版本的稳定性&#xff0c;我们可以在设置中将Update: Mode设置为none&#xff0c;这样就不会触发自动更新。但有时又有版本更新的需求&#xff0c;可能是版本…

医疗超声成像专用AFE模拟前端

医疗超声成像作为一种广泛应用于临床诊断的重要技术&#xff0c;对于提供清晰、准确的医学图像起着关键作用。在超声成像系统中&#xff0c;AFE模拟前端扮演着至关重要的角色。它负责对超声换能器接收到的微弱电信号进行处理和转换&#xff0c;为后续的数字信号处理提供高质量的…

机器学习之线性回归——小白教学

一、线性回归简介1.什么是线性回归线性回归(Linear regression)是利⽤回归⽅程(函数)对⼀个或多个⾃变量(特征值)和因变量(⽬标值)之间关系进⾏建模的⼀种分析⽅式。特点&#xff1a;只有⼀个⾃变量的情况称为单变量回归&#xff0c;多于⼀个⾃变量情况的叫做多元回归线性回…

.NET 10 中的新增功能系列文章1——运行时中的新增功能

引言 随着 .NET 10 预览版6的发布&#xff0c;微软在运行时层面带来了一系列重要的性能改进和新功能。这些改进主要集中在JIT编译器优化、硬件指令集支持、内存管理等方面&#xff0c;旨在进一步提升应用程序的执行效率和资源利用率。本文将详细解析这些运行时增强功能&#x…

安宝特方案丨AI算法能力开放平台:适用于人工装配质检、点检、实操培训

当前工业AI图形识别算法的应用存在投入成本高、维护更新难、依赖固定相机、应用范围窄、与实际作业脱节等问题。 针对以上情况&#xff0c;安宝特提出了“AI算法能力开放平台”&#xff0c;目的是让AI图形识别算法可以与现场实际的人工点检作业、装配作业、质检作业、培训作业…

水下目标识别准确率↑89%!陌讯多模态融合算法在智慧水务的落地实践

一、行业痛点&#xff1a;智慧水务的检测困境据《2024城市水务智能化白皮书》统计&#xff0c;传统水务检测面临三大挑战&#xff1a;​​水体干扰​​&#xff1a;浑浊度>100NTU时&#xff0c;目标漏检率高达65%​​动态环境​​&#xff1a;水流扰动导致目标形变&#xff…

手动开发一个串口调试工具(三):基于 Qt Widgets 搭建串口调试界面

在上一篇中&#xff0c;我们通过 QCoreApplication 构建了一个基础的串口收发控制台程序&#xff0c;并实现了周期发送、十六进制转换和数据读取等核心功能。本篇将基于此逻辑&#xff0c;进一步将其封装为一个图形化界面程序&#xff0c;借助 Qt Widgets 提供的控件搭建完整的…

量子计算革命:重新定义计算的边界与未来

引言&#xff1a;我们正站在计算革命的新起点 当IBM在2019年宣布实现"量子霸权"时&#xff0c;很多人认为这只是实验室里的科学突破。然而&#xff0c;短短几年后&#xff0c;量子计算已经从理论走向实践&#xff0c;从实验室走向产业应用。我们正站在一个全新的计算…

Python 数据可视化之 Matplotlib 库

在当今数据驱动的时代&#xff0c;数据可视化&#xff08;Data Visualization&#xff09;已成为数据科学、机器学习、金融分析、工程建模等多个领域中不可或缺的一环。数据可视化不仅帮助我们更直观地理解数据的分布和趋势&#xff0c;还能辅助决策、展示研究成果以及增强数据…

Makefile 快速入门指南

Makefile 快速入门指南 什么是Makefile? Makefile 是一个自动化构建工具的配置文件&#xff0c;用于管理代码编译、测试和清理等任务。它通过定义规则&#xff08;rules&#xff09;来指定文件之间的依赖关系&#xff0c;当源文件改变时&#xff0c;只重新编译受影响的部分&…

Linux学习--C语言(指针4、结构体)

1.二维数组的传参int a[2][3] {1, 2, 3, 4, 5, 6};fun(a,2); int fun(int (*p)[3], int len);2.指针数组的传参char *pastr[5] {NULL};int fun(char **pstr,int len);例子&#xff1a;#include <stdio.h> #include <string.h>int InputArray(char (*p)[32], int …

【STM32】FreeRTOS 消息队列(五)

在 FreeRTOS 中&#xff0c;任务消息队列&#xff08;Message Queue&#xff09; 是一种非常关键的通信机制&#xff0c;用于在任务之间 传递数据、同步事件。 它是实现任务 解耦、异步通信 的核心工具之一&#xff0c;FreeRTOS 的消息队列是任务之间通信的桥梁。 简单点说&am…

【笔记】加速 uv 安装:系统环境变量配置国内镜像源

使用 Conda 工具链创建 UV 本地虚拟环境全记录——基于《Python 多版本与开发环境治理架构设计》-CSDN博客 命令行创建 UV 环境及本地化实战演示—— 基于《Python 多版本与开发环境治理架构设计》的最佳实践-CSDN博客 加速 uv 包安装&#xff1a;Windows 系统环境变量配置国内…