欸嘿嘚哟 2024-03-17 21:46 采纳率: 0%
浏览 5

Spring动态代理转账案例中事务手动提交无反应

SpringAOP 中转账案例问题
在学习JDK动态代理技术时遇见,编写事务管理类并设置完setAutoCommit(false) 后,本应该手动提交事务的,但是即使不调用commite 方法也会自动提交事务

TransactionManager .java

    public void startTransaction(){
        // 获取一个连接对象
//        Connection threadConnection = connectionUtils.getThreadConnection();
        try {
            // 开启手动提交事务
                connectionUtils.getThreadConnection().setAutoCommit(false);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }

这里已经设置了自动提交为false,但最终调用该方法开启事务后,不调用提交事务的方法,发现数据库的值依旧会变化,然后去查数据库的事务提交时,发现自动提交的设置依旧是默认自动

JDKProxyFactory .java(代理类增强转账方法)

                try {
                    // 开启手动提交事务
                    transactionManager.startTransaction();

                    // 目标对象方法执行
                    method.invoke(accountService, args);

                    // 没有提交事务欸,为什么能成功?!orn

                } catch (Exception e) {
                    e.printStackTrace();
                    // 报错执行回滚方法
                    transactionManager.rollback();
                } finally {
                    // 资源的释放
                    transactionManager.release();
                }

然后就是数据库中表数据依旧发生了变化,报错回滚倒是没有问题,这样显得我很o_o
求各位帮忙解解惑!orn

  • 写回答

4条回答 默认 最新

  • 关注

    m0_73668824 晚上好🌙🌙🌙
    本答案参考ChatGPT-3.5

    问题的关键在于使用了Spring的事务管理器(TransactionManager)和动态代理技术实现的代理类,但是事务没有生效,即使设置了自动提交为false也无效。

    这个问题可能是因为在Spring中,事务管理器通常与连接对象(Connection)绑定,而在动态代理类中,获取连接对象的方法是通过一个工具类(connectionUtils)来获取的,这两者之间的连接对象并不是同一个。

    所以,在动态代理类中设置连接对象的自动提交是无效的,因为这个连接对象和事务管理器绑定的连接对象不同。

    解决这个问题的思路可以是将连接对象的获取与事务管理器绑定起来,确保在事务管理器开启事务的时候获取到的连接对象是同一个。

    解决方法如下:

    1. 在事务管理器(TransactionManager)中添加一个成员变量,用于存储连接对象(Connection)。
    2. 在事务管理器(TransactionManager)中添加一个获取连接对象的方法,并将获取到的连接对象存储到成员变量中。
    3. 修改动态代理类中获取连接对象的方式,将其改为从事务管理器(TransactionManager)中获取连接对象。
    4. 在动态代理类中设置连接对象的自动提交为false,并执行目标对象的方法。
    5. 在动态代理类中提交事务或回滚事务的时候,使用事务管理器(TransactionManager)中保存的连接对象。

    修改后的代码示例:

    TransactionManager.java:

    public class TransactionManager {
        private Connection connection;
    
        public Connection getConnection() {
            return connection;
        }
    
        public void startTransaction() {
            try {
                connection = connectionUtils.getThreadConnection();
                connection.setAutoCommit(false);
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    
        public void commit() {
            try {
                connection.commit();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    
        public void rollback() {
            try {
                connection.rollback();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    
        public void release() {
            try {
                connection.close();
                connectionUtils.removeThreadConnection();
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
        }
    }
    

    JDKProxyFactory.java:

    public class JDKProxyFactory implements InvocationHandler {
        private Object target;
    
        public Object getProxy(Object target) {
            this.target = target;
            return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            TransactionManager transactionManager = new TransactionManager();
    
            try {
                transactionManager.startTransaction();
    
                // 设置连接对象的自动提交为false
                transactionManager.getConnection().setAutoCommit(false);
    
                // 执行目标对象的方法
                Object result = method.invoke(target, args);
    
                // 提交事务
                transactionManager.commit();
    
                return result;
            } catch (Exception e) {
                // 回滚事务
                transactionManager.rollback();
                e.printStackTrace();
                throw e;
            } finally {
                // 释放资源
                transactionManager.release();
            }
        }
    }
    

    通过以上的修改,可以确保事务管理器中的连接对象与动态代理类中的连接对象是同一个,这样就能够正确地控制事务的提交和回滚。

    评论

报告相同问题?

问题事件

  • 创建了问题 3月17日

悬赏问题

  • ¥15 P1口接8个发光二极管,利用定时计数器1编写程序
  • ¥20 keil5编译找不到.h文件该如何解决
  • ¥15 安卓EVS如何开启服务正常实现功能
  • ¥15 canal读取mysql时报错
  • ¥15 关于 S7-PLCSIM Advanced 5.0本地TCP连接无法读写数据
  • ¥15 关于温度改变石墨烯介电性能(关键词-介电常数)
  • ¥150 HDMI分路器LT86102 的输出在890MHz频点处EMC超标8DB
  • ¥15 druid(相关搜索:数据库|防火墙)
  • ¥15 大一python作业
  • ¥15 preLaunchTask"C/C++: aarch64- apple-darwin22-g++-14 生成活动 文件”已终止,退出代码为-1。