JDBC事务(transaction)

第一章事务操作

1.1Mysql事务操作

略,详情见mysql笔记中

1.2JDBC事务操作

Connection对象的方法名

描述

conn.setAutoCommit(false);

开启事务

conn.commit();

提交事务

conn.rollback();

回滚事务

示例代码:


package Transaction;

import jdbc.JdbcUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;public class Demo01 {

    public static void main(String[] args) throws SQLException {
        //模拟转账
        //1.获取连接
        Connection connection = null;      
        Statement statement = null;
        try {
            connection = JdbcUtils.getConnection();
            //1.开启事务
            connection.setAutoCommit(false);
            String sql1 = "update account  set cash= cash-100 where `name` ='zhangsan'";
            String sql2 = "update account  set cash= cash+100 where `name` ='lisi'";
            //2.加钱,减钱
            statement = connection.createStatement();
            statement.executeUpdate(sql1);
            int i = 1 / 0;   //模拟收款人加钱时出错。
            statement.executeUpdate(sql2);
            //2.提交事务
            connection.commit();
        } catch (Exception e) {
            connection.rollback();  //3.回滚事务
        } finally {
            //3.关闭资源
            JdbcUtils.closeResource(connection, statement, null);
        }
    }
}

1.3DBUtils

Connection对象的方法名

描述

conn.setAutoCommit(false);

开启事务

DbUtils.commitAndCloseQuietly(conn);

提交事务并且关闭连接

DbUtils.rollbackAndCloseQuietly(conn);

回滚事务 并且关闭连接

new QueryRunner()

创建核心类

query(conn,sql,handler,params)或者

执行sql语句

update(conn,sql,params)

执行sql语句

package Transaction;

import jdbc.JdbcUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;

import java.sql.Connection;

public class Demo02 {
    public static void main(String[] args) {
        Connection connection = null;
        try {
            //1.开启事务
            connection = JdbcUtils.getConnection();
            connection.setAutoCommit(false);
            String sql1 = "update account set cash=cash-100 where `name`='zhangsan'";
            String sql2 = "update account set cash=cash+100 where `name`='lisi'";
            QueryRunner queryRunner = new QueryRunner();
            queryRunner.update(connection, sql1);
            int i =1/0;
            queryRunner.update(connection, sql2);
            //2.提交事务
            DbUtils.commitAndCloseQuietly(connection);
        } catch (Exception e) {
            //3.回滚事务
            DbUtils.rollbackAndCloseQuietly(connection);
        }
    }
}

第二章 事务总结

2.1ACID回顾:

原子性:原子性是指事务是不可分割的,要么都发生,要么都不发生。

一致性:事务前后的数据必须保持一致。

隔离性:事务的隔离性就是一个事务不能呗其他事务干扰。

持久性:事务一旦提交,对数据的改变就是永久的。

2.2事务并发问题

脏读:一个事务读到了另外一个事务没有提交的数据

1.在事务A执行的过程中,事务A对数据进行了修改,事务B读取到了事务A修改后的数据

2.由于某些原因,事务A并没有完成提交,发生了回滚操作,所以B读到了不该读到的脏数据。

这种读取到另外一个事务没有提交的数据的现象就是脏读(Dirty Read)。

不可重复读:事务B读取了两次数据资源,在这两次数据资源读取的过程中,事务A修改了数据,导致事务B在两次读取中的数据不一致,在这种同一个事务中,两次读取数据不一致的现象出现 ,就是不可重复读。

幻读/虚读:事务B前后两次读取同一个范围数据,在事务B进行中,事务A新增了数据,导致事务B后面读的和前面一次查询的不一致。

2.3隔离级别:解决问题

数据库规范了4种隔离级别,分别用于解决事务并发产生的所有情况,事务隔离级别从低到高分别是:读未提交,读已提交,可重复读,串行化。

级别越高,越能保证数据的一致性和完整性,但是执行效率也就越低,所以设置数据库的隔离级别需要做以下权衡。

Mysql默认的是可重复读的级别。

读未提交:是最低的隔离级别,所有的事务都能看到其他未提交的事务的执行结果,不能解决脏读,幻读,可重复读,所以很少应用于实际开发中。

读已提交:在这个隔离级别下,一个事务的更新操作结果只有在该事务提交之后,另一个事务才能读取到同一笔数据的更新结果。可以防止脏读出现,但是不能解决可重复读和幻读的问题。

可重复读:Mysql默认的隔离级别。在这个隔离级别下,一个事务多次读同一个数据,如果这个事务还没有结束,其他事务不能访问该数据(包括读写)。这样就能保证两次读到的数据是一样的。可以预防脏读,不可重复读,但是还是会出现幻读。

串行化:这是最高的隔离级别,要求事务序列化的执行,事务只能排队一个接着一个的执行。强制要求事务不能并发执行。可以解决上面的所有问题,但是会导致大量的超时出现,通常情况下不使用该隔离级别。

  • 9
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值