修改数据源驱动

This commit is contained in:
tangw 2026-08-12 10:08:38 +08:00
parent 61687b4b4a
commit c90ab1a102
5 changed files with 214 additions and 4 deletions

View File

@ -116,7 +116,18 @@
<groupId>com.microsoft.sqlserver</groupId> <groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId> <artifactId>mssql-jdbc</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
</dependency>
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver8</artifactId>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>

View File

@ -0,0 +1,29 @@
package com.czlis.system.config;
import com.czlis.system.interceptor.SqlPlusToConcatInterceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import javax.annotation.Resource;
import java.util.Map;
@Configuration
public class MyBatisPluginConfig {
@Resource
private ApplicationContext applicationContext;
@Bean
public ApplicationListener<ContextRefreshedEvent> registerInterceptor() {
return event -> {
Map<String, SqlSessionFactory> map = applicationContext.getBeansOfType(SqlSessionFactory.class);
SqlPlusToConcatInterceptor interceptor = new SqlPlusToConcatInterceptor();
for (SqlSessionFactory sf : map.values()) {
sf.getConfiguration().addInterceptor(interceptor);
}
};
}
}

View File

@ -0,0 +1,153 @@
package com.czlis.system.interceptor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* SQLServer转达梦 MyBatis SQL兼容拦截器
* 全部正则模式,不依赖JSqlParser解析器,解决低版本jar包类缺失问题
* 注意:该模式无法区分数字相加和字符串拼接,SQL尽量不要同时出现数字+运算
*/
@Intercepts({
@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class SqlPlusToConcatInterceptor implements Interceptor {
private static final Logger log = LoggerFactory.getLogger(SqlPlusToConcatInterceptor.class);
// '常量'+col 或者 col+'常量'
private static final Pattern CONCAT_PATTERN = Pattern.compile("(\\s*'[^']*'\\s*\\+|\\+\\s*'[^']*')");
// CHARINDEX(a,b)
private static final Pattern CHARINDEX_PATTERN = Pattern.compile("CHARINDEX\\s*\\(\\s*(.+?)\\s*,\\s*(.+?)\\s*\\)", Pattern.CASE_INSENSITIVE);
// ISNULL(a,b)
private static final Pattern ISNULL_2PARAM_PATTERN = Pattern.compile("ISNULL\\s*\\(\\s*(.+?)\\s*,\\s*(.+?)\\s*\\)", Pattern.CASE_INSENSITIVE);
// RIGHT(REPLICATE(' ',N)+expr,N)
private static final Pattern RIGHT_REPLICATE_PATTERN = Pattern.compile(
"RIGHT\\s*\\(\\s*REPLICATE\\s*\\(\\s*'\\s*'\\s*,\\s*(\\d+)\\s*\\)\\s*\\+\\s*(.+?)\\s*,\\s*(\\d+)\\s*\\)",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL
);
// REPLICATE(str,N)
private static final Pattern REPLICATE_PATTERN = Pattern.compile(
"REPLICATE\\s*\\(\\s*(.+?)\\s*,\\s*(\\d+)\\s*\\)",
Pattern.CASE_INSENSITIVE | Pattern.DOTALL
);
@Override
public Object intercept(Invocation invocation) throws Throwable {
log.info("====进入SQL兼容拦截器====");
StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String originSql = boundSql.getSql();
Connection connection = (Connection) invocation.getArgs()[0];
DatabaseMetaData metaData = connection.getMetaData();
String productName = metaData.getDatabaseProductName();
boolean enableConvert = productName != null && productName.toUpperCase().contains("DM");
log.info("识别数据库产品名称:[{}], 是否开启SQL兼容转换:{}", productName, enableConvert);
try {
if (!enableConvert) {
return invocation.proceed();
}
String lowerSql = originSql.trim().toLowerCase();
if (lowerSql.startsWith("call ") || lowerSql.startsWith("exec ")) {
return invocation.proceed();
}
String targetSql = originSql;
StringBuffer sb = new StringBuffer();
//1. RIGHT(REPLICATE(' ',N)+expr,N) → SUBSTR(LPAD(expr,N,' '),1,N)
Matcher mRightRep = RIGHT_REPLICATE_PATTERN.matcher(targetSql);
sb.setLength(0);
while (mRightRep.find()) {
String num = mRightRep.group(1).trim();
String expr = mRightRep.group(2).trim();
String newExpr = String.format("SUBSTR(LPAD(%s,%s,' '),1,%s)", expr, num, num);
mRightRep.appendReplacement(sb, Matcher.quoteReplacement(newExpr));
}
mRightRep.appendTail(sb);
targetSql = sb.toString();
//2. 'xxx' + col / col + 'xxx' 加号替换为 ||
Matcher mConcat = CONCAT_PATTERN.matcher(targetSql);
sb.setLength(0);
while (mConcat.find()) {
String found = mConcat.group();
mConcat.appendReplacement(sb, Matcher.quoteReplacement(found.replace("+", "||")));
}
mConcat.appendTail(sb);
targetSql = sb.toString();
//3. CHARINDEX(a,b) → INSTR(b,a)
Matcher mCharIndex = CHARINDEX_PATTERN.matcher(targetSql);
sb.setLength(0);
while (mCharIndex.find()) {
String p1 = mCharIndex.group(1).trim();
String p2 = mCharIndex.group(2).trim();
String newFunc = String.format("INSTR(%s,%s)", p2, p1);
mCharIndex.appendReplacement(sb, Matcher.quoteReplacement(newFunc));
}
mCharIndex.appendTail(sb);
targetSql = sb.toString();
//4. ISNULL(a,b) → NVL(a,b)
Matcher mIsnull = ISNULL_2PARAM_PATTERN.matcher(targetSql);
sb.setLength(0);
while (mIsnull.find()) {
String p1 = mIsnull.group(1).trim();
String p2 = mIsnull.group(2).trim();
String newFunc = String.format("NVL(%s,%s)", p1, p2);
mIsnull.appendReplacement(sb, Matcher.quoteReplacement(newFunc));
}
mIsnull.appendTail(sb);
targetSql = sb.toString();
//5. REPLICATE(str,N) → REPEAT(str,N)
Matcher mRep = REPLICATE_PATTERN.matcher(targetSql);
sb.setLength(0);
while (mRep.find()) {
String src = mRep.group(1).trim();
String cnt = mRep.group(2).trim();
String newFunc = String.format("REPEAT(%s,%s)", src, cnt);
mRep.appendReplacement(sb, Matcher.quoteReplacement(newFunc));
}
mRep.appendTail(sb);
targetSql = sb.toString();
//回填修改后的SQL
if (!originSql.equals(targetSql)) {
log.debug("【SQL兼容转换】\n原SQL:\n{}\n转换后:\n{}", originSql, targetSql);
org.apache.ibatis.reflection.MetaObject metaObject
= org.apache.ibatis.reflection.SystemMetaObject.forObject(statementHandler);
metaObject.setValue("delegate.boundSql.sql", targetSql);
}
} catch (Exception e) {
log.warn("【SQL转换处理异常,直接放行原始SQL】sql:{} , ex:{}", originSql, e.getMessage());
}
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
}

19
pom.xml
View File

@ -308,7 +308,24 @@
<artifactId>mssql-jdbc</artifactId> <artifactId>mssql-jdbc</artifactId>
<version>${sqlserver.version}</version> <version>${sqlserver.version}</version>
</dependency> </dependency>
<!--金仓数据库 驱动-->
<dependency>
<groupId>cn.com.kingbase</groupId>
<artifactId>kingbase8</artifactId>
<version>8.2.0</version>
</dependency>
<!--达梦数据库 驱动-->
<dependency>
<groupId>com.dameng</groupId>
<artifactId>DmJdbcDriver8</artifactId>
<version>8.1.5.45</version>
</dependency>
<!--sql语句拦截器工具-->
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>4.6</version>
</dependency>
<!-- 中文转拼音 --> <!-- 中文转拼音 -->
<dependency> <dependency>
<groupId>com.belerweb</groupId> <groupId>com.belerweb</groupId>

View File

@ -6,7 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="getReportsList" resultType="com.czlis.zybgcx.pojo.Web_getReportsList"> <select id="getReportsList" resultType="com.czlis.zybgcx.pojo.Web_getReportsList">
<![CDATA[select * from web_getReportsList where jyrq >= CONVERT(varchar(100), #{st}, 120) and jyrq <= CONVERT(varchar(100), #{et}, 120)]]> select * from web_getReportsList where jyrq >= #{st} and #{et} >= jyrq
<if test="brxm != null and brxm != ''"> AND brxm like '%'+#{brxm}+'%'</if> <if test="brxm != null and brxm != ''"> AND brxm like '%'+#{brxm}+'%'</if>
<if test="brdh != null and brdh != ''"> AND brdh like '%'+#{brdh}+'%'</if> <if test="brdh != null and brdh != ''"> AND brdh like '%'+#{brdh}+'%'</if>
<if test="sqh != null and sqh != ''"> AND sqh like '%'+#{sqh}+'%'</if> <if test="sqh != null and sqh != ''"> AND sqh like '%'+#{sqh}+'%'</if>
@ -14,7 +14,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="ksdh !=null and ksdh != ''"> and ksdh = #{ksdh}</if> <if test="ksdh !=null and ksdh != ''"> and ksdh = #{ksdh}</if>
<if test="alarmflag != null"> <![CDATA[AND alarmflag = #{alarmflag}]]></if> <if test="alarmflag != null"> <![CDATA[AND alarmflag = #{alarmflag}]]></if>
<if test="ch != null and ch !=''"> and ch = #{ch}</if> <if test="ch != null and ch !=''"> and ch = #{ch}</if>
<if test="jzbz != null">and jzbz = #{jzbz}</if> <if test="jzbz != null and jzbz !='' ">and jzbz = #{jzbz}</if>
<if test="brlyname != null and brlyname != ''"> and brlyname = #{brlyname}</if> <if test="brlyname != null and brlyname != ''"> and brlyname = #{brlyname}</if>
<if test="lisgroup != null and lisgroup != ''"> and lisgroup = #{lisgroup}</if> <if test="lisgroup != null and lisgroup != ''"> and lisgroup = #{lisgroup}</if>
<if test="yq != null and yq != ''"> and yq = #{yq}</if> <if test="yq != null and yq != ''"> and yq = #{yq}</if>