yumeng 1 天之前
父节点
当前提交
3ba29af78e

+ 94 - 0
jeecg-boot-material-view/src/main/java/org/jeecg/ctop/material/service/impl/SafeTiFlashInterceptor.java

@@ -0,0 +1,94 @@
+package org.jeecg.ctop.material.service.impl;
+
+
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.plugin.*;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.reflection.SystemMetaObject;
+import org.springframework.stereotype.Component;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.sql.Statement;
+import java.util.Properties;
+
+/**
+ * 使用MetaObject安全获取字段的TiFlash拦截器
+ */
+@Intercepts({
+        @Signature(type = Executor.class, method = "query",
+                args = {MappedStatement.class, Object.class,
+                        org.apache.ibatis.session.RowBounds.class,
+                        org.apache.ibatis.session.ResultHandler.class})
+})
+@Component
+public class SafeTiFlashInterceptor implements Interceptor {
+
+    @Override
+    public Object intercept(Invocation invocation) throws Throwable {
+        try {
+            // 使用MetaObject安全获取字段
+            Executor executor = (Executor) invocation.getTarget();
+            MetaObject metaObject = SystemMetaObject.forObject(executor);
+
+            // 获取transaction
+            Object transaction = metaObject.getValue("transaction");
+            if (transaction == null) {
+                // 尝试其他可能的字段名
+                transaction = metaObject.getValue("delegate.transaction");
+            }
+
+            if (transaction != null) {
+                // 获取connection
+                MetaObject transactionMeta = SystemMetaObject.forObject(transaction);
+                Connection connection = (Connection) transactionMeta.getValue("connection");
+
+                if (connection != null) {
+                    // 如果是代理连接,获取原始连接
+                    connection = getRealConnection(connection);
+
+                    try (Statement stmt = connection.createStatement()) {
+                        stmt.execute("SET session tidb_isolation_read_engines = 'tiflash,tidb'");
+                        System.out.println("✅ TiFlash引擎设置成功");
+                    }
+                }
+            }
+        } catch (Exception e) {
+            // 记录错误但不中断流程
+            System.err.println("TiFlash设置失败: " + e.getMessage());
+            // e.printStackTrace(); // 调试时打开
+        }
+
+        return invocation.proceed();
+    }
+
+    /**
+     * 获取真实的Connection对象(处理代理)
+     */
+    private Connection getRealConnection(Connection connection) {
+        try {
+            if (Proxy.isProxyClass(connection.getClass())) {
+                // 如果是代理对象,尝试获取委托对象
+                java.lang.reflect.InvocationHandler handler = Proxy.getInvocationHandler(connection);
+                if (handler instanceof org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory) {
+                    // MyBatis代理
+                    return (Connection) handler.getClass()
+                            .getMethod("getTarget")
+                            .invoke(handler);
+                }
+            }
+        } catch (Exception e) {
+            // 如果获取失败,返回原始连接
+        }
+        return connection;
+    }
+
+    @Override
+    public Object plugin(Object target) {
+        return Plugin.wrap(target, this);
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+    }
+}

+ 0 - 112
jeecg-boot-material-view/src/main/java/org/jeecg/ctop/material/service/impl/TiFlashInterceptor.java

@@ -1,112 +0,0 @@
-package org.jeecg.ctop.material.service.impl;
-
-
-import org.apache.ibatis.executor.Executor;
-import org.apache.ibatis.mapping.MappedStatement;
-import org.apache.ibatis.mapping.SqlCommandType;
-import org.apache.ibatis.plugin.*;
-import org.springframework.stereotype.Component;
-import java.sql.Connection;
-import java.sql.Statement;
-import java.util.Properties;
-
-/**
- * MyBatis拦截器,在执行SQL前设置TiFlash引擎
- * 最简单的TiFlash配置方案
- */
-@Intercepts({
-        @Signature(type = Executor.class, method = "query",
-                args = {MappedStatement.class, Object.class,
-                        org.apache.ibatis.session.RowBounds.class,
-                        org.apache.ibatis.session.ResultHandler.class}),
-        @Signature(type = Executor.class, method = "update",
-                args = {MappedStatement.class, Object.class})
-})
-@Component  // 关键:添加@Component注解让Spring管理
-public class TiFlashInterceptor implements Interceptor {
-
-    private static final String SET_SQL =
-            "SET session tidb_isolation_read_engines = 'tiflash,tidb'";
-
-    // ThreadLocal记录每个连接是否已设置,避免重复设置
-    private ThreadLocal<Boolean> tiFlashSet = ThreadLocal.withInitial(() -> false);
-
-    @Override
-    public Object intercept(Invocation invocation) throws Throwable {
-        try {
-            // 获取MappedStatement
-            MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
-
-            // 只对SELECT查询设置TiFlash(可选,根据需求调整)
-            if (ms.getSqlCommandType() == SqlCommandType.SELECT) {
-                setTiFlashIfNeeded(invocation);
-            }
-            // 如果要对所有SQL都设置,可以去掉上面的if判断
-
-        } catch (Exception e) {
-            // 捕获异常但不中断SQL执行
-            System.err.println("TiFlash拦截器异常: " + e.getMessage());
-        }
-
-        // 继续执行原始SQL
-        return invocation.proceed();
-    }
-
-    /**
-     * 设置TiFlash引擎(如果需要)
-     */
-    private void setTiFlashIfNeeded(Invocation invocation) {
-        try {
-            // 检查是否已设置
-            if (tiFlashSet.get()) {
-                return; // 已设置,跳过
-            }
-
-            // 获取数据库连接
-            Connection connection = getConnection(invocation);
-            if (connection != null) {
-                try (Statement stmt = connection.createStatement()) {
-                    stmt.execute(SET_SQL);
-                    tiFlashSet.set(true); // 标记已设置
-                    System.out.println("✅ TiFlash引擎已设置");
-                }
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-            System.err.println("设置TiFlash失败: " + e.getMessage());
-        }
-    }
-
-    /**
-     * 通过反射获取当前数据库连接
-     */
-    private Connection getConnection(Invocation invocation) throws Exception {
-        // 获取Executor对象
-        Executor executor = (Executor) invocation.getTarget();
-
-        // 反射获取transaction字段
-        java.lang.reflect.Field transactionField =
-                Executor.class.getDeclaredField("master");
-        transactionField.setAccessible(true);
-        Object transaction = transactionField.get(executor);
-
-        // 反射获取connection字段
-        java.lang.reflect.Field connectionField =
-                transaction.getClass().getDeclaredField("connection");
-        connectionField.setAccessible(true);
-
-        return (Connection) connectionField.get(transaction);
-    }
-
-    @Override
-    public Object plugin(Object target) {
-        // 包装目标对象
-        return Plugin.wrap(target, this);
-    }
-
-    @Override
-    public void setProperties(Properties properties) {
-        // 可以读取配置文件中的属性
-        System.out.println("TiFlash拦截器初始化...");
-    }
-}