本地事务与Spring的事务特性(小白篇)

版权声明:禁止转载 https://blog.csdn.net/qq_36505948/article/details/88083264

一、事务类型

事务可以分为本地事务和分布式事务两种类型。这两种事务类型是根据访问并更新的数据资源的多少来进行区分的。本地事务是在单个数据源上进行数据的访问和更新,而分布式事务是跨越多个数据源来进行数据的访问和更新。在这里要说的事务是基于数据库这种数据源的。

JDBC事务

在JAVA中,我们使用JDBC来连接数据库,访问和更新数据。那么在JDBC中是如何实现事务的,事务是被谁来管理的?这个答案当然是数据库,JDBC本身并没有处理事务的能力,而是依赖于底层数据库,底层数据库来提供事务的服务。在很多资料上会提到,JDBC的事务是基于连接的,也就是那个Connection对象,这个连接的本质其实是连接到数据库的一个Socket,与数据库建立连接以后就可以向数据库发送指令和数据,最终数据库会根据接收到的指令和数据来进行增删改查以及事务的处理。另外,事务是被限制在单个连接上的,这就好像我们去银行的营业厅办理业务,营业厅有多个窗口,我们只会在自己的窗口上与银行工作人员进行沟通并处理自身的业务,而不能跨窗口,告诉别的窗口的工作人员把那哥们的钱转到自己卡上,这事也就只能想想。

以上这段代码来自于网络,感谢该博友:https://www.cnblogs.com/nobounds/p/5415062.html

这里需要说明的是:本地事务的事务性是默认自动提交的,并且只有在同一个数据源才能生效是什么意思?这里的数据源只的是我们配置完数据后,通过Connection对象创建的入口。一个connection就是一个独立的数据源,而本地事务是指在通过这一个本地事务提交的过程中,他默认提供给我们的单操作性事务。如下便是一个本地事务:

package person.lb.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;


public class TestJDBCTransAction {

    static {
        try {
            //加载驱动类
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 
    }
    
    public static void main(String[] args) {
        //执行事务
        executeTransaction();
    }

    private static void executeTransaction() {
        Connection conn = null;
        Statement st1 = null;
        Statement st2 = null;
        ResultSet rs = null;
        try {
            //获取数据库连接
            conn = (Connection) DriverManager.getConnection(
                    "jdbc:mysql://192.168.0.105:3306/TEST", 
                    "root", 
                    "root");
            conn.setAutoCommit(false);
            
            st1 = (Statement) conn.createStatement();
            st2 = (Statement) conn.createStatement();
            //插入用户信息
            st1.execute("INSERT INTO USERS (USER_NAME, PASSWORD, GENDER, PHONE_NO) "
                      + "VALUES ('zhangsan', '123456', '男', '11111111111')"
                      , Statement.RETURN_GENERATED_KEYS);
            //获取增长列的新值
            rs = st1.getGeneratedKeys();
            String userID = "";
            if(rs.next()) {
                userID = rs.getString(1);
            }
            //插入用户和角色关联数据
            st2.execute("INSERT INTO USER_ROLE_RELATION (USER_ID, ROLE_ID) VALUES (" +userID +", '1')");
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
            try {
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
        } finally {
            try {
                if(rs != null) {
                    rs.close();
                }
                if(st1 != null) {
                    st1.close();
                }
                if(st2 != null) {
                    st2.close();
                }
                if(conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

通过同一个connection对象提供出来的单连接 , 即是一个单操作性的本地事务。对于多语句的操作他同时提供了人工提交事务和回滚的三个办法!

1.setAutoCommit()
2.commit()
3.rollback()

 说完本地事务就需要说明spring提供的事务了,也就是文章博友所说的分布式事务。这里的分布式在我看来是在于事务方法模块的分散。也即是可能存在多个数据源连接。比如A方法是对数据库做了增操作,操作的同时又调用了B方法,而B方法是对数据库的又一次操作,AB方法的协作共同完成了本次的功能单元,这个功能单元对我们来说就是分布式事务。


二、分布式事务

Spriing的分布式事务,是怎么理解的呢?各个实现方法之间的事务关系应该如何?如果我想将两个方法设置为两个事务应该如何,如果我想将两个方法不执行事务应该如何,如果我想让两个方法中正确的提交,失败的不提交应该如何?这是属于Spring的事务传播性问题,一般情况下,对于不清楚的则容易混淆!此篇指在入门。

Spring的事务控制支持是统一在TransactionalDefinition中类描述,它提供了以下:

1.事务的传播特性,七种类型:getPropagationBehavior()

2.事务隔离级别:getlsolationLevel()

3.事务过期时间:getTimeOut()

4.事务读写特性:isReadOnly()

除了事务的传播性行为是由于spring提供的框架支持,其他的都是Spring调用底层的资源,为之提供代理。


所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。Spring 支持 7 种事务传播行为:

PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。(频繁使用)

PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行PROPAGATION_REQUIRED 类似的操作。

猜你喜欢

转载自blog.csdn.net/qq_36505948/article/details/88083264