JDBC-事务

JDBC-事务

MySQL 事务主要用于处理操作量大,复杂度高的数据

事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行

数据库中有很多关于事务的命令

命令说明
SHOW VARIABLES LIKE 'autocommit'查看当前连接中事物的提交方式(ON自动提交 OFF关闭自动提交)
SET autocommit = FALSE设置当前连接事务提交方式为手动提交
COMMIT提交事务
ROLLBACK回滚事务

事务的回滚

如果有两条语句要执行,可以看数据的受影响行数

如果当前连接受影响行数小于预期受影响行数,就说明有语句执行失败,需要事务回滚


JDBC工具类的优化

对工具类进行修改,在回收连接前开启自动提交(关闭事务),再将连接回收

public static void close() {
    try {
        //从theadlocal中获取到连接,判断是否有线程
        //如果有,该连接回收到连接池,并将threadlocal中的连接移除
        Connection connection = threadLocal.get();
        if (connection != null) {
            threadLocal.remove();
            //开启自动提交(关闭事务)
            connection.setAutoCommit(true);
            connection.close();
        }
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

对BaseDAO进行修改,在两个方法中对工具类的连接的回收加以判定

if (connection.getAutoCommit())
{
    JDBCUtilV2.close();
}

这样操作之后,开启事务(关闭自动提交)时,将不会由BaseDAO接管连接的回收

即不会再执行完SQL方法时自动回收链接,需要在业务层自己操作回收链接


业务层代码

在业务层中,我们有三个关键的操作

  • 开启事务(关闭自动提交):connection.setAutoCommit(false)
  • 提交事务:connection.commit()
  • 回滚事务:connection.rollback()

注:事务的开启,connection.setAutoCommit是针对这一连接的,要保证业务连接的唯一性,我们需要用到JDBCUtilV2中的threadLocal

@Test
public void testTransaction(){
    UserDao userDao = new UserDaoImpl();
    Connection connection = null;
    try {
        connection = JDBCUtilV2.getConnection();
        connection.setAutoCommit(false);//关闭自动提交(开启事务)

        userDao.addMoney(1,200);
        userDao.addMoney(2,200);
        
        connection.commit();//提交事务
    } catch (SQLException e) {
        try {
            connection.rollback();//当出现异常时,事务自动回滚
        } catch (SQLException ex) {
            throw new RuntimeException(e);
        }
        throw new RuntimeException(e);
    } finally {
        //BaseDAO检测到事务开启(自动提交关闭),则不会自动回收连接,所以在Finally中回收连接
        JDBCUtilV2.close();
    }