DataSourceUtils(加入线程管理事务)

第一二见之前的文章:

DataSourceUtils(使用C3P0连接池的工具类)

替换第三步:

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

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DataSourceUtils {
    private static ComboPooledDataSource ds=new ComboPooledDataSource();
    private static ThreadLocal<Connection> tl=new ThreadLocal<>();
    
    /**
     * 获取数据源
     * @return 连接池
     */
    public static DataSource getDataSource(){
        return ds;
    }
    
    /**
     * 从当前线程上获取连接
     * @return 连接
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException{
        Connection conn = tl.get();
        if(conn==null){
            //第一次获取 创建一个连接 和当前的线程绑定
             conn=ds.getConnection();
             
             //绑定
             tl.set(conn);
        }
        return conn;
    }
    
    
    
    /**
     * 释放资源
     * 
     * @param conn
     *            连接
     * @param st
     *            语句执行者
     * @param rs
     *            结果集
     */
    public static void closeResource(Connection conn, Statement st, ResultSet rs) {
        closeResource(st, rs);
        closeConn(conn);
    }
    
     
    public static void closeResource(Statement st, ResultSet rs) {
            closeResultSet(rs);
            closeStatement(st);
    }

    /**
     * 释放连接
     * 
     * @param conn
     *            连接
     */
    public static void closeConn(Connection conn) {
        if (conn != null) {
            try {
                conn.close();
                //和当前的线程解绑
                tl.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }

    }

    /**
     * 释放语句执行者
     * 
     * @param st
     *            语句执行者
     */
    public static void closeStatement(Statement st) {
        if (st != null) {
            try {
                st.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            st = null;
        }

    }

    /**
     * 释放结果集
     * 
     * @param rs
     *            结果集
     */
    public static void closeResultSet(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }

    }
    
    /**
     * 开启事务
     * @throws SQLException
     */
    public static void startTransaction() throws SQLException{
        //获取连接//开启事务
        getConnection().setAutoCommit(false);;
    }
    
    /**
     * 事务提交
     */
    public static void commitAndClose(){
        try {
            //获取连接
            Connection conn = getConnection();
            //提交事务
            conn.commit();
            //释放资源
            conn.close();
            //解除绑定
            tl.remove();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 事务回滚
     */
    public static void rollbackAndClose(){
        try {
            //获取连接
            Connection conn = getConnection();
            //事务回滚
            conn.rollback();
            //释放资源
            conn.close();
            //解除绑定
            tl.remove();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

 

转载于:https://www.cnblogs.com/NEWHOM/p/6715768.html

<think>嗯,用户问的是Spring事务的执行流程。这个我得先回忆一下Spring事务管理的基本原理。首先,Spring的事务管理是基于AOP(面向切面编程)实现的,对吧?然后,事务的入口应该是通过@Transactional注解或者XML配置来声明事务边界。 接下来,我需要分步骤来梳理整个流程。首先,当调用一个被@Transactional标记的方法时,Spring会创建一个事务的切面,也就是事务拦截器。这个拦截器会在方法执行前开启事务,然后在方法执行后根据情况提交或回滚事务。但具体的步骤可能更详细。 比如,事务的开始可能涉及到获取数据库连接,设置自动提交为false。然后执行目标方法,如果方法正常结束,就提交事务,否则回滚。不过中间可能还有各种传播机制的处理,比如如果当前已经存在事务,就根据传播行为决定是加入还是新建事务。 还有,Spring的事务管理是通过PlatformTransactionManager来管理的,不同的数据源可能需要不同的事务管理器,比如DataSourceTransactionManager用于JDBC,而JpaTransactionManager用于JPA。这也可能在流程中起作用。 另外,事务的隔离级别和超时时间这些属性是如何被应用到事务中的呢?应该是在事务开始时通过设置连接的相关参数来配置的。异常处理方面,默认情况下只有运行时异常和Error才会回滚,检查型异常不会,除非特别指定。 可能用户还关心事务的传播行为,比如REQUIRED、REQUIRES_NEW这些,不同的传播行为会影响事务的创建和加入方式。这部分也需要在流程中说明。 不过用户可能不需要太深入的细节,比如底层的具体实现类,但关键步骤需要讲清楚。比如,代理对象的创建、事务拦截器的触发、事务属性的解析、事务管理器的作用,以及提交或回滚的条件。 还有,Spring的事务是通过动态代理或者CGLIB代理来实现的,所以在调用方法时,实际上是经过代理对象的方法,从而织入事务管理的逻辑。这一点可能也是流程的一部分。 总结一下,流程大概可以分为以下几个步骤: 1. 代理对象的创建:Spring为被@Transactional注解的Bean创建代理。 2. 方法调用进入事务拦截器。 3. 检查是否存在事务,根据传播行为决定创建新事务还是加入现有事务。 4. 获取数据库连接,设置事务属性(隔离级别、超时等)。 5. 执行目标方法。 6. 根据方法执行结果(是否有异常、异常类型)决定提交或回滚事务。 7. 清理事务资源,释放连接。 需要注意不同传播行为下的处理,比如REQUIRES_NEW会挂起当前事务,新建一个独立的事务。还有嵌套事务的处理可能涉及到保存点的使用。 另外,事务同步管理器(TransactionSynchronizationManager)在管理事务资源和同步状态中扮演重要角色,比如绑定当前线程事务资源。 可能用户没有提到具体的传播行为或隔离级别,但了解整个流程需要涵盖这些方面。不过作为介绍,可以简要提及这些因素如何影响流程。 最后,确保回答结构清晰,分步骤说明,并用用户容易理解的语言,避免过于技术化的术语堆砌,同时保持准确性。</think>Spring事务执行流程可分为七个核心步骤,以下结合代码示例进行说明: 1. **代理对象创建阶段** ```java // Spring通过AOP为@Transactional注解的Bean生成代理对象 @Transactional public class UserService { public void transferMoney() { /*...*/ } } ``` 2. **事务拦截器触发** ```java // 事务拦截器TransactionInterceptor介入方法调用 public class TransactionInterceptor extends TransactionAspectSupport { public Object invoke(MethodInvocation invocation) { /*...*/ } } ``` 3. **事务属性解析** ```java // 解析@Transactional注解属性 DefaultTransactionAttribute txAttr = new AnnotationTransactionAttributeSource() .getTransactionAttribute(method, targetClass); ``` 4. **事务管理器选择** ```java // 根据数据源选择对应的事务管理器 PlatformTransactionManager tm = determineTransactionManager(txAttr); ``` 5. **事务开启与资源绑定** ```java // 获取数据库连接并关闭自动提交 Connection conn = DataSourceUtils.getConnection(dataSource); conn.setAutoCommit(false); // 绑定到当前线程 TransactionSynchronizationManager.bindResource(dataSource, conn); ``` 6. **目标方法执行** ```java try { // 执行实际业务逻辑 invocation.proceed(); } catch (Exception ex) { // 异常处理 completeTransactionAfterThrowing(txInfo, ex); throw ex; } ``` 7. **事务提交/回滚** ```java // 正常执行后提交 if (txStatus.isNewTransaction()) { tm.commit(txStatus); } // 异常时回滚(默认对RuntimeException回滚) if (rollbackOn(ex)) { tm.rollback(txStatus); } else { tm.commit(txStatus); } ``` **核心流程详解**: 1. 当调用被`@Transactional`注解的方法时,实际调用的是Spring生成的代理对象 2. 事务拦截器通过AOP切入方法执行流程 3. 根据传播行为处理事务上下文: - `PROPAGATION_REQUIRED`:存在事务加入,否则新建 - `PROPAGATION_REQUIRES_NEW`:始终新建独立事务 - `PROPAGATION_NESTED`:使用保存点实现嵌套事务 4. 通过`TransactionSynchronizationManager`进行线程事务资源管理 5. 实际数据库操作延迟到事务提交时才批量执行(JDBC批处理优化) **异常处理机制**: - 默认回滚规则:RuntimeException和Error触发回滚 - 可通过`rollbackFor`自定义回滚异常类型 - 检查型异常默认不触发回滚,需显式配置 **传播行为对流程的影响示例**: ```java @Transactional(propagation = Propagation.REQUIRES_NEW) public void methodA() { // 始终开启新事务 methodB(); // 如果methodB是REQUIRED,将加入当前新事务 } @Transactional(propagation = Propagation.REQUIRED) public void methodB() { // 根据上下文决定是否新建事务 } ``` 该流程通过AOP和线程绑定机制,实现了声明式事务管理,使
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值