diff --git a/lis-system/pom.xml b/lis-system/pom.xml
index cabec75..170fa69 100644
--- a/lis-system/pom.xml
+++ b/lis-system/pom.xml
@@ -116,7 +116,18 @@
com.microsoft.sqlserver
mssql-jdbc
-
+
+ cn.com.kingbase
+ kingbase8
+
+
+ com.dameng
+ DmJdbcDriver8
+
+
+ com.github.jsqlparser
+ jsqlparser
+
org.springframework.boot
spring-boot-starter-test
diff --git a/lis-system/src/main/java/com/czlis/system/config/MyBatisPluginConfig.java b/lis-system/src/main/java/com/czlis/system/config/MyBatisPluginConfig.java
new file mode 100644
index 0000000..2e1f7c4
--- /dev/null
+++ b/lis-system/src/main/java/com/czlis/system/config/MyBatisPluginConfig.java
@@ -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 registerInterceptor() {
+ return event -> {
+ Map map = applicationContext.getBeansOfType(SqlSessionFactory.class);
+ SqlPlusToConcatInterceptor interceptor = new SqlPlusToConcatInterceptor();
+ for (SqlSessionFactory sf : map.values()) {
+ sf.getConfiguration().addInterceptor(interceptor);
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/lis-system/src/main/java/com/czlis/system/interceptor/SqlPlusToConcatInterceptor.java b/lis-system/src/main/java/com/czlis/system/interceptor/SqlPlusToConcatInterceptor.java
new file mode 100644
index 0000000..b535557
--- /dev/null
+++ b/lis-system/src/main/java/com/czlis/system/interceptor/SqlPlusToConcatInterceptor.java
@@ -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) {
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 206eccd..f194409 100644
--- a/pom.xml
+++ b/pom.xml
@@ -308,7 +308,24 @@
mssql-jdbc
${sqlserver.version}
-
+
+
+ cn.com.kingbase
+ kingbase8
+ 8.2.0
+
+
+
+ com.dameng
+ DmJdbcDriver8
+ 8.1.5.45
+
+
+
+ com.github.jsqlparser
+ jsqlparser
+ 4.6
+
com.belerweb
diff --git a/zybgcx/src/main/resources/mapper/ZybgcxMapper.xml b/zybgcx/src/main/resources/mapper/ZybgcxMapper.xml
index e3b6b3f..7f7b93c 100644
--- a/zybgcx/src/main/resources/mapper/ZybgcxMapper.xml
+++ b/zybgcx/src/main/resources/mapper/ZybgcxMapper.xml
@@ -6,7 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"