Spring 事务系列 - 编程式事务

什么是事务?

数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。

事务应该具有4个属性:原子性、一致性、隔离性、持久性,这四个属性通常称为ACID特性。
* 原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
* 一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致状态的含义是数据库中的数据应满足完整性约束。
* 隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
* 持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。

事务的隔离级别

在数据库操作中,为了有效保证并发读取数据的正确性,提出的事务隔离级别。我们的数据库锁,也是为了构建这些隔离级别存在的。

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
读未提交(Read uncommitted)可能可能可能
读已提交(Read committed)不可能可能可能
可重复读(Repeatable read)不可能不可能可能
可串行化(Serializable )不可能不可能不可能

说明:
* 读未提交(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
* 读已提交(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
* 可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
* 串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞

Read Uncommitted这种级别,数据库一般都不会用,而且任何操作都不会加锁,这里就不讨论了。MySQL默认的事务隔离级别为可重复读(Repeated Read)。

一、编程式事务

在 Spring 出现以前,编程式事务管理对开发者来说是唯一选择。熟悉Java JDBC 的人都知道,我们需要在代码中显式调用Connection 的setAutoCommit()、commit()、rollback()等事务管理相关的方法,这就是编程式事务管理。

1、JDBC 的编程式事务管理

public void save(User user) throws SQLException{
    Connection conn = datasource.getConnection();
    conn.setAutoCommit(false);
    try {
        PreparedStatement ps = conn.prepareStatement("insert into user(name,age) value(?,?)");
        ps.setString(1,user.getName());
        ps.setInt(2,user.getAge());
        ps.execute();
        conn.commit();
    } catch (Exception e) {
        e.printStackTrace();
        conn.rollback();
    }finally{
        conn.close();
    }
}

2、Hibernate 的编程式事务管理

Hibernate 中需要显式调用beginTransaction()、commit()、rollback()等事务管理相关的方法,如下:

public void save(User user){
    Session session = hibernateDao.openSession();
    Transaction tx = null;
    try {
        tx = session.beginTransaction();  
        session.save(user);  
        tx.commit();  
    } catch (Exception e) {
        if(tx!=null){
            tx.rollback();
        }
    }finally{
        session.close();
    }
}

3、MyBatis 的编程式事务管理

MyBatis中,我们可以通过org.apache.ibatis.session.SqlSession 的commit()、rollback() 等事务管理相关的方法,代码如下:

    String resource = "org/mybatis/example/mybatis-config.xml";
    InputStream in = Resources.getResourceAsStream(resource);
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);

    SqlSession session = sqlSessionFactory.openSession(false); // 打开会话,事务开始  
    try {  
        IUserMapper mapper = session.getMapper(IUserMapper.class);  
        User user = new User(9, "Test transaction");  
        int affectedCount = mapper.updateUser(user); // 因后面的异常而未执行commit语句  
        User user = new User(10, "Test transaction continuously");  
        int affectedCount2 = mapper.updateUser(user2); // 因后面的异常而未执行commit语句  
        int i = 2 / 0; // 触发运行时异常  
        session.commit(); // 提交会话,即事务提交  
    } catch (Exception e) {
        session.rollback(); //回滚
    } finally {  
        session.close(); // 关闭会话,释放资源  
    }  

参考资料

分布式事务系列(1.2)Spring的事务体系:https://yq.aliyun.com/articles/39046?spm=5176.100239.blogcont39044.27.mmXvhw

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值