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
英文地址,請注明出處:http://en.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 系統環境變量配置國內…