@Transactional声明式事务

spring事务特性

TransactionDefinition接口定义以下特性:

事务隔离级别

隔离级别是指若干个并发的事务之间的隔离程度。TransactionDefinition 接口中定义了五个表示隔离级别的常量:

TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是TransactionDefinition.ISOLATION_READ_COMMITTED。

TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。

TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。

TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。

TransactionDefinition.ISOLATION_SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

事务传播行为

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。在TransactionDefinition定义中包括了如下几个表示传播行为的常量:

TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。

TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

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

TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。

事务超时

所谓事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。

默认设置为底层事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是none,没有超时限制。

*事务只读属性*

只读事务用于客户代码只读但不修改数据的情形,只读事务用于特定情景下的优化,比如使用Hibernate的时候。
默认为读写事务。

spring事务回滚规则

指示spring事务管理器回滚一个事务的推荐方法是在当前事务的上下文内抛出异常。spring事务管理器会捕捉任何未处理的异常,然后依据规则决定是否回滚抛出异常的事务。

默认配置下,spring只有在抛出的异常为运行时unchecked异常时才回滚该事务,也就是抛出的异常为RuntimeException的子类(Errors也会导致事务回滚),而抛出checked异常则不会导致事务回滚。
可以明确的配置在抛出那些异常时回滚事务,包括checked异常。也可以明确定义那些异常抛出时不回滚事务。

还可以编程性的通过setRollbackOnly()方法来指示一个事务必须回滚,在调用完setRollbackOnly()后你所能执行的唯一操作就是回滚。

@Transactional注解

@Transactional属性

属性类型描述
valueString可选的限定描述符,指定使用的事务管理器
propagationenum: Propagation可选的事务传播行为设置
isolationenum: Isolation可选的事务隔离级别设置
readOnlyboolean读写或只读事务,默认读写
timeoutint (in seconds granularity)事务超时时间设置
rollbackForClass对象数组,必须继承自Throwable导致事务回滚的异常类数组
rollbackForClassName类名数组,必须继承自Throwable导致事务回滚的异常类名字数组
noRollbackForClass对象数组,必须继承自Throwable不会导致事务回滚的异常类数组
noRollbackForClassName类名数组,必须继承自Throwable不会导致事务回滚的异常类名字数组

用法

在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。

@Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。

注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。

通过 元素的 "proxy-target-class" 属性值来控制是基于接口的还是基于类的代理被创建。如果 "proxy-target-class" 属值被设置为 "true",那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 "proxy-target-class" 属值被设置为 "false" 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。
标准的JDK基于接口的代理将起作用-->
proxy-target-class="false"/>

基于类的代理将起作用 ,同时 cglib.jar必须在CLASSPATH中
proxy-target-class="true"/>
-->
非JTA事务(即非分布式事务), 事务配置的时候 ,需要指定dataSource属性(非分布式事务,事务是在数据库创建的链接上开启。)-->

JTA事务(非分布式事务), 事务配置的时候 ,不能指定dataSource属性(分布式事务,是有全局事务来管理数据库链接的)-->
注解@Transactional cglib与java动态代理最大区别是代理目标对象不用实现接口,那么注解要是写到接口方法上,要是使用cglib代理,这是注解事物就失效了,为了保持兼容注解最好都写到实现类方法上。

Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

@Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。
public interface PersonService {
//删除指定id的person
public void delete(Integer personid) ;

//删除指定id的person,flag
public void delete(Integer personid,boolean flag) ;
}

public class PersonServiceBean implements PersonService {
private JdbcTemplate jdbcTemplate;

public void delete(Integer personid){
   try{
       this.delete(personid,true)
       System.out.println("delete success");
   }catch(Exception e){
       System.out.println("delete failed");
   }
}
@Transactional
//此时,事务根本就没有开启, 即数据库会默认提交该操作,即记录别删除掉 public void delete(Integer personid,boolean flag){
  if(flag == ture){
      jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
      new int[]{java.sql.Types.INTEGER});
      throw new RuntimeException("运行期例外");
   }
 }
}

public class PersonServiceBeanTest{
    PersonService ps = new PersonServiceBean ();
    ps.delete(5);
}
  1. Spring使用声明式事务处理,默认情况下,如果被注解的数据库操作方法中发生了unchecked异常,所有的数据库操作将rollback;如果发生的异常是checked异常,默认情况下数据库操作还是会提交的。

    public interface PersonService {
       //删除指定id的person
       public void delete(Integer personid) ;
    
       //获取person
       public Person getPerson(Integer personid);
    }
    
    //PersonServiceBean 实现了PersonService 接口,则基于接口的还是基于类的代理 都可以实现事务
    @Transactional 
    public class PersonServiceBean implements PersonService {
       private JdbcTemplate jdbcTemplate;
    
       //发生了unchecked异常,事务回滚, @Transactional
        public void delete(Integer personid){
           jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
             new int[]{java.sql.Types.INTEGER});
             throw new RuntimeException("运行期例外");
        }
    }
    
    public interface PersonService {
       //删除指定id的person
       public void delete(Integer personid) throws Exception;
    
       //获取person
       public Person getPerson(Integer personid);
    }
    
    @Transactional
    public class PersonServiceBean implements PersonService {
    
    //发生了checked异常,事务不回滚,即数据库记录仍能被删除,
    //checked的例外,需要我们在外部用try/catch语法对调用该方法的地方进行包含 @Transactional
    public void delete(Integer personid) throws Exception{
    jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
    new int[]{java.sql.Types.INTEGER});
    throw new Exception("运行期例外");
    }
    
    }
    
    但是,对于checked这种例外,默认情况下它是不会进行事务回滚的,但是如果我们需要它进行事务回滚,这时候可以在delete方法上通过@Transaction这个注解来修改它的行为。
    
@Transactional
public class PersonServiceBean implements PersonService {

@Transactional(rollbackFor=Exception.class)
//rollbackFor这属性指定了,既使你出现了checked这种例外,那么它也会对事务进行回滚
public void delete(Integer personid) throws Exception{
jdbcTemplate.update("delete from person where id=?", new Object[]{personid},
new int[]{java.sql.Types.INTEGER});
throw new Exception("运行期例外");
}
}
在PersonServiceBean这个业务bean里面,有一些事务是不需要事务管理的,好比说获取数据的getPersons方法,getPerson方法。因为@Transactional 放在了类的上面。


此时,可以采用propagation这个事务属性@Transactional(propagation=Propagation.NOT_SUPPORTED),propagation这个属性指定了事务传播行为,我们可以指定它不支持事务,当我们这么写了之后,Spring容器在getPersons方法执行前就不会开启事务.
@Transactional
public class PersonServiceBean implements PersonService {

    @Transactional(propagation=Propagation.NOT_SUPPORTED)
    //则此方法 就不会开启事务了
    public Person getPerson(Integer personid){
     }
}
<think>好的,我现在需要回答用户关于@Transactional声明式事务传播行为类型的问题。首先,我得回忆一下Spring事务传播行为的相关知识。传播行为是Spring事务管理中的一个重要概念,它定义了事务方法在调用其他事务方法时,事务应该如何传播。用户提到了“春秋表”,可能是笔误,应该是“传播行为类型”的列表。 根据记忆,Spring的传播行为类型有七种,分别是REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。每个类型都有不同的行为。例如,REQUIRED是默认的,如果当前没有事务,就新建一个,如果有就加入。REQUIRES_NEW则是无论当前是否存在事务,都新建一个,同时挂起当前事务。这些需要详细解释。 接下来,我需要确认这些类型是否正确,以及它们的实际应用场景。比如,MANDATORY要求必须在已有事务中运行,否则抛出异常,适用于必须要有事务支持的场景。而NOT_SUPPORTED则是在无事务状态下运行,如果当前有事务则挂起。这些区别对于正确使用事务非常重要。 然后,用户提供的引用内容中提到了Spring事务的实现原理和配置切入点表达式,这可能和传播行为的配置有关。在声明式事务中,通过@Transactional注解的属性来指定传播行为类型,比如@Transactional(propagation = Propagation.REQUIRED)。需要结合AOP的配置,如引用[2]中的切入点表达式,来定义哪些方法应用这些事务属性。 此外,要确保回答结构清晰,分点说明每种传播行为类型,并给出示例代码。同时,生成的相关问题需要覆盖用户可能感兴趣的方面,比如配置方式、嵌套事务、选择依据等。最后,引用文献需要正确对应到用户提供的引用内容,确保引用标识正确。</think>### @Transactional声明式事务的传播行为类型 Spring声明式事务通过`@Transactional`注解实现事务管理,其中`propagation`属性用于定义事务的传播行为。传播行为决定了事务方法在调用其他事务方法时,事务的边界如何控制。以下是7种传播行为类型及其说明: #### 1. **REQUIRED(默认)** - **行为**:如果当前存在事务,则加入该事务;否则新建一个事务。 - **应用场景**:适用于多数业务逻辑需要事务支持的场景。 - **示例**: ```java @Transactional(propagation = Propagation.REQUIRED) public void methodA() { ... } ``` #### 2. **SUPPORTS** - **行为**:如果当前存在事务,则加入;否则以非事务方式执行。 - **应用场景**:适用于查询操作,允许灵活适应调用环境。 - **示例**: ```java @Transactional(propagation = Propagation.SUPPORTS) public void queryData() { ... } ``` #### 3. **MANDATORY** - **行为**:必须在已有事务中运行,否则抛出异常。 - **应用场景**:强制要求方法必须在事务上下文中调用。 - **示例**: ```java @Transactional(propagation = Propagation.MANDATORY) public void updateData() { ... } ``` #### 4. **REQUIRES_NEW** - **行为**:无论当前是否存在事务,都新建一个事务,并挂起当前事务(如果存在)。 - **应用场景**:需要独立事务的操作(如日志记录),避免外层事务回滚影响。 - **示例**: ```java @Transactional(propagation = Propagation.REQUIRES_NEW) public void logOperation() { ... } ``` #### 5. **NOT_SUPPORTED** - **行为**:以非事务方式执行,若当前存在事务则挂起。 - **应用场景**:执行不需要事务支持的操作(如文件操作)。 - **示例**: ```java @Transactional(propagation = Propagation.NOT_SUPPORTED) public void processFile() { ... } ``` #### 6. **NEVER** - **行为**:必须在非事务环境中执行,否则抛出异常。 - **应用场景**:确保方法不会在事务中被调用。 - **示例**: ```java @Transactional(propagation = Propagation.NEVER) public void validateInput() { ... } ``` #### 7. **NESTED** - **行为**:在当前事务中创建一个嵌套事务。外层事务回滚时,嵌套事务也会回滚;但嵌套事务可独立提交或回滚。 - **支持条件**:需底层数据库支持保存点(如MySQL的InnoDB)。 - **应用场景**:复杂业务中部分操作需要独立回滚。 - **示例**: ```java @Transactional(propagation = Propagation.NESTED) public void subTask() { ... } ``` --- ### 配置传播行为的方式 在`@Transactional`注解中直接指定`propagation`属性即可: ```java @Transactional(propagation = Propagation.REQUIRED) public void transactionalMethod() { ... } ``` 通过AOP配置(如XML),可结合切入点表达式批量定义事务属性,如引用[2]中的配置: ```xml <aop:config> <aop:pointcut id="pt" expression="execution(* cn.bdqn.service.impl.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/> </aop:config> ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值