Spring 事物机制

Spring两种事物处理机制,一是声明式事物,二是编程式事物

 

 声明式事物

 1)Spring的声明式事务管理在底层是建立在AOP的基础之上的。

  其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

  声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过等价的基于标注的方式),便可以将事务规则应用到业务逻辑中。因为事务管理本身就是一个典型的横切逻辑,正是AOP的用武之地。Spring开发团队也意识到了这一点,为声明式事务提供了简单而强大的支持。Spring强大的声明式事务管理功能,这主要得益于Spring依赖注入容器和Spring AOP的支持。依赖注入容器为声明式事务管理提供了基础设施,使得Bean对于Spring框架而言是可管理的;而Spring AOP则是声明式事务管理的直接实现者。

  和编程式事务相比,声明式事务唯一不足地方是,后者的最细粒度只能作用到方法级别,无法做到像编程式事务那样可以作用到代码块级别。但是即便有这样的需求,也存在很多变通的方法,比如,可以将需要进行事务管理的代码块独立为方法等等。

 

 2)5种配置方式

  Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。
关系图如下:

 实例代码如下:

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="configLocation" value="classpath:hibernate.cfg.xml" />
    <property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
</bean>

<!-- 定义事务管理器(声明式的事务) -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

注意:sessionFactorty和transactionManager是下面5中配置方式的基本配置,

 

 第一种方式:每个Bean都有一个代理

 

<!-- 配置DAO -->
<bean id="userDaoTarget" class="com.test.spring.dao.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="userDao" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <!-- 配置事务管理器 -->
    <property name="transactionManager" ref="transactionManager" />
    <property name="target" ref="userDaoTarget" />
    <property name="proxyInterfaces" value="com.test.spring.dao.GeneratorDao" />
    <!-- 配置事务属性 -->
    <property name="transactionAttributes">
        <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

 

 

 第二种方式:所有Bean共享一个代理基类

<bean id="transactionBase" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" lazy-init="true" abstract="true">  
    <!-- 配置事务管理器 -->  
    <property name="transactionManager" ref="transactionManager" />  
    <!-- 配置事务属性 -->  
    <property name="transactionAttributes">  
        <props>  
            <prop key="*">PROPAGATION_REQUIRED</prop>  
        </props>  
    </property>  
</bean>  
  
<!-- 配置DAO -->  
<bean id="userDaoTarget" class="com.test.spring.dao.UserDaoImpl">  
    <property name="sessionFactory" ref="sessionFactory" />  
</bean>  
  
<bean id="userDao" parent="transactionBase">  
    <property name="target" ref="userDaoTarget" />  
</bean>  

 

 

 第三种方式:使用拦截器

<bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
    <property name="transactionManager" ref="transactionManager" />
    <!-- 配置事务属性 -->
    <property name="transactionAttributes">
        <props>
            <prop key="*">PROPAGATION_REQUIRED</prop>
        </props>
    </property>
</bean>

<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
    <property name="beanNames">
        <list>
            <value>*Dao</value>
        </list>
    </property>
    <property name="interceptorNames">
        <list>
            <value>transactionInterceptor</value>
        </list>
    </property>
</bean>

<!-- 配置DAO -->
<bean id="userDao" class="com.test.spring.dao.UserDaoImpl">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

 

 

 第四种方式:使用tx标签配置的拦截器    

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="interceptorPointCuts"
        expression="execution(* com.test.spring.dao.*.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="interceptorPointCuts" />
</aop:config>    

 

 第五种方式:全注解

public class test {
    @Transactional
    public class UserDaoImpl extends HibernateDaoSupport implements UserDao {

        public List<User> listUsers() {
            return null
        }
    }
}

 

 

 

 编程式事务

Spring的编程式事务即在代码中使用编程的方式进行事务处理,可以做到比声明式事务更细粒度。有两种方式一是使用TransactionManager,另外就是TransactionTemplate。

 1)TransactionManager使用方式

public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
    private HibernateTransactionManager transactionManager;
    private DefaultTransactionDefinition def;

    public HibernateTransactionManager getTransactionManager() {
        return transactionManager;
    }

    public void setTransactionManager(HibernateTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    public void createTransactionDefinition() {
        def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
    }

    public void saveOrUpdate(User user) {
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            this.getHibernateTemplate().saveOrUpdate(user);
        } catch (DataAccessException ex) {
            transactionManager.rollback(status);
            throw ex;
        }
        transactionManager.commit(status);
    }
}

 

 

 

 2)TransactionTemplate方式

 

ResultDto ret = null;
ret = (ResultDto) this.transactionTemplate.execute(new TransactionCallback() {
    @Override
    public Object doInTransaction(TransactionStatus status) {
        ResultDto ret = null;
        try {
            drillTaskDao.deleteByKey(taskid);
        } catch (Exception e) {
            logger.error("delDrillTask:" + e.getMessage(), e);
            ret = ResultBuilder.buildResult(ResultBuilder.FAIL_CODE, null, ErrorCode.COM_DBDELETEERROR);
            return ret;
        }
        finally {
            status.setRollbackOnly();
        }
         
        ret = cleartaskrelativedata(taskid, appid, true);
        return ret;
    }
});
return ret;

 

转载于:https://www.cnblogs.com/hwaggLee/p/4461667.html

<think>首先,用户的问题是:“我想了解Spring框架中事务的传播机制有哪些 请问Spring事务传播机制类型有哪些”。这直接询问Spring事务传播机制的类型。 根据系统级指令: - 所有行内数学表达式必须使用 $...$ 格式,但在这个上下文中,可能没有数学表达式,所以我可以忽略。 - 独立公式必须使用 $$...$$ 格式并单独成段,同样,可能不适用。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 用户提供了几个引用: - 引用[1]:提到Spring的事务传播机制,包括事务特性、传播机制类型如REQUIRED、SUPPORTS等。 - 引用[2]:解释Spring事务传播机制基于AOP和事务管理器实现。 - 引用[3]:提到Spring通过@Transactional注解支持声明式事务,传播行为是关键参数。 - 引用[4]:详细描述了传播机制类型,特别是NESTED,并举例说明。 - 引用[5]:给出一个@Transactional注解的例子,包括propagation参数。 我需要基于这些引用构建回答。用户的问题是询问传播机制的类型,所以我应该列出并解释常见的传播机制类型。 常见的Spring事务传播机制类型包括: 1. REQUIRED 2. SUPPORTS 3. MANDATORY 4. REQUIRES_NEW 5. NOT_SUPPORTED 6. NEVER 7. NESTED 这些在引用[1]和[4]中明确提到。 我的回答结构应该清晰: - 先简要介绍什么是事务传播机制。 - 然后列出并解释每个类型。 - 最后生成相关问题。 使用中文回答。 添加引用:在解释时,自然地添加引用标识。例如,当提到某个类型时,引用相关来源。 生成相关问题:在回答末尾添加“相关问题”部分,就像示例中那样。 逐步回答: 1. 介绍事务传播机制:简要解释什么是传播机制,基于引用[2]和[3]。 2. 列出类型:基于引用[1]和[4]。 - REQUIRED:如果当前有事务,加入它;否则,新建事务。 - SUPPORTS:如果当前有事务,加入它;否则,非事务执行。 - MANDATORY:如果当前有事务,加入它;否则,抛出异常。 - REQUIRES_NEW:挂起当前事务,新建一个事务。 - NOT_SUPPORTED:挂起当前事务,非事务执行。 - NEVER:非事务执行;如果当前有事务,抛出异常。 - NESTED:如果当前有事务,创建一个嵌套事务;否则,新建事务。 3. 解释每个类型时,参考引用[4]的例子。 4. 添加引用标识:例如,在描述后添加 [^1] 或 [^4]。 生成相关问题: - 类似示例,如: 1. 如何选择合适的传播机制? 2. Spring事务传播机制的实现原理是什么? 3. NESTED传播机制的具体应用场景? 确保回答真实可靠:基于提供的引用,不添加额外信息,除非必要。 最终回答结构: - 开头:介绍传播机制。 - 主体:列出每个类型并解释。 - 结尾:相关问题。</think>### Spring事务传播机制类型介绍 在Spring框架中,事务传播机制定义了当一个事务方法调用另一个事务方法时,事务如何传播或处理。这是基于AOP(面向切面编程)和事务管理器(如DataSourceTransactionManager)实现的[^2]。通过@Transactional注解,开发者可以指定传播行为,这是声明式事务管理的关键参数之一[^3]。Spring提供了7种标准的事务传播机制类型,每种类型适用于不同的场景。下面我将逐一解释这些类型,确保内容清晰可靠。 #### 事务传播机制类型 1. **REQUIRED** 如果当前存在活动事务,则加入该事务;如果不存在,则新建一个事务。这是最常用的传播机制,适用于大多数业务场景。例如,在服务调用链中,确保所有操作在同一个事务中执行[^1][^4]。 2. **SUPPORTS** 如果当前存在活动事务,则加入该事务;如果不存在,则以非事务方式执行。适用于查询操作或不需要严格事务保证的场景[^1][^3]。 3. **MANDATORY** 如果当前存在活动事务,则加入该事务;如果不存在,则抛出异常。这强制要求方法必须在事务上下文中调用,常用于确保数据一致性[^1][^4]。 4. **REQUIRES_NEW** 挂起当前事务(如果存在),并新建一个独立的事务。新事务提交或回滚不影响原始事务。适用于需要隔离操作的场景,如日志记录或外部服务调用[^1][^4]。 5. **NOT_SUPPORTED** 挂起当前事务(如果存在),并以非事务方式执行。适用于不需要事务支持的操作,例如只读任务或性能敏感场景[^1][^3]。 6. **NEVER** 以非事务方式执行;如果当前存在活动事务,则抛出异常。这确保方法不会被事务上下文干扰,常用于纯查询方法[^1][^4]。 7. **NESTED** 如果当前存在活动事务,则创建一个嵌套事务(作为子事务);如果不存在,则新建一个事务。嵌套事务可以独立回滚,但不影响父事务提交。使用场景示例: - 如果ServiceA(传播机制REQUIRED)调用ServiceB(传播机制NESTED),当ServiceA异常时,整个事务回滚(包括ServiceB)。 - 如果ServiceB异常,ServiceA可以捕获异常后正常提交,而ServiceB单独回滚[^4]。 这适用于需要部分回滚的复杂业务逻辑。 #### 使用示例 在代码中,可以通过@Transactional注解指定传播机制类型,例如: ```java @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED) public void exampleMethod() { // 业务逻辑 } ``` 这里,propagation参数定义了传播行为,其他参数如isolation(隔离级别)可结合使用[^5]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值