spring事务失效问题分析及解决方案怎么做,spring 事务失效情况

spring事务失效问题分析及解决方案怎么做,spring 事务失效情况,Spring事务失效问题分析及解决方案

本文主要介绍Spring事务失效的分析和解决方法,通过实例代码详细介绍,对大家的学习或工作有一定的参考价值。有需要的朋友可以参考一下。

本文主要介绍Spring事务失效的分析和解决方法,通过实例代码详细介绍,对大家的学习或工作有一定的参考价值。有需要的朋友可以参考一下。

隔离级别

在TransactionDefinition.java接口中,定义了四种隔离级别枚举:

/**

Spring特有]使用后端数据库的默认隔离级别。

*

* MySQL默认采用REPEATABLE_READ隔离级别

*默认情况下,Oracle采用READ_COMMITTED隔离级别。

*/

int ISOLATION _ DEFAULT=-1;

/**

*最低隔离级别允许读取未提交的数据更改,这可能会导致脏读取、幻像读取或不可重复读取。

*/

int ISOLATION _ READ _ UNCOMMITTED=Connection。TRANSACTION _ READ _ UNCOMMITTED

/**

*允许读取已经由并发事务提交的数据,这可以防止脏读,但仍可能出现幻读或不可重复读。

*/

int ISOLATION _ READ _ COMMITTED=Connection。TRANSACTION _ READ _ COMMITTED

/**

*同一个字段多次读取的结果是一致的,除非数据被自己的事务修改,这样可以防止脏读和不可重复读取,但幻读还是有可能发生。

*/

int ISOLATION _ REPEATABLE _ READ=Connection。TRANSACTION _ REPEATABLE _ READ

/**

*最高隔离级别,完全服从ACID的隔离级别。的所有事务都是一个一个依次执行的,所以事务之间绝对没有干扰,也就是这个级别可以防止脏读、不可重复读和幻影读。

*

*但这会严重影响程序的性能。通常不使用这个级别。

*/

int ISOLATION _ SERIALIZABLE=Connection。TRANSACTION _ SERIALIZABLE

事务的传播级别

事务传播行为是指当前具有事务配置的方法,以及如何处理事务;例如,一个方法可以在现有的事务中继续运行,也可以启动一个新的事务并在自己的事务中运行;

注意,事务的传播级别不是数据库事务规范中的一个术语,而是由Spring本身定义的。通过事务的传播层,Spring知道如何处理事务,是创建新事务还是继续使用当前事务;

在TransactionDefinition.java接口中,定义了三种类型和七个传播级别:

//=======支持当前事务=======

/**

*如果事务当前存在,则使用它。

*如果当前没有交易,请创建一个新的交易。

*/

int PROPAGATION _ REQUIRED=0;

/**

*如果事务当前存在,则使用它。

*如果当前没有事务,继续以非事务方式运行。

*/

int PROPAGATION _ SUPPORTS=1;

/**

*如果事务当前存在,则使用它。

*如果当前没有事务,抛出异常。

*/

int PROPAGATION _ MANDATORY=2;

//=======不支持当前事务=======

/**

*创建新交易。

*如果有当前事务,暂停当前事务。

*/

int PROPAGATION _ REQUIRES _ NEW=3;

/**

*以非事务方式运行。

*如果有当前事务,暂停当前事务。

*/

int PROPAGATION _ NOT _ SUPPORTED=4;

/**

*以非事务方式运行。

*如果当前存在事务,则会引发异常。

*/

int PROPAGATION _ NEVER=5;

//======其他情况========

/**

*如果当前存在事务,则创建一个事务作为当前事务的嵌套事务运行。

*如果当前没有事务,则相当于{ @ linktransactiondefinition # propagation _ required }

*/

int PROPAGATION _ NESTED=6;

@Transaction

@事务标注由Spring的tx模块提供,使用AOP实现事务控制,即底层是动态代理;

@Transaction可以作用于接口、接口方法、类和类方法;当在类上使用时,该类的所有公共方法都将具有这种类型的transaction属性,或者您可以在方法级别使用此注释来覆盖类级别的定义。

事务失效

1.异常类型错误,默认是运行时异常才会回滚

2.异常被捕捉后没有抛出,需要抛异常才能回滚

3.是否发生自身调用的问题

4.注解所在位置是否为公众的修饰

5.数据源没有配置事务管理器

6.不支持事务的引擎,如米沙姆

下面是一个事务失效的例子

@Slf4j

@服务

公共类OrderServiceImpl实现订单服务{

@自动连线

私有顺序映射器;

@事务性

@覆盖

public void parent() {

尝试{

这个。child();

} catch(异常e) {

log.error('插入异常,e);

}

订单Order=new Order();

秩序。setorderno(“parent”);

秩序。设置状态(" 0 ");

秩序。settitle(“父”);

秩序。设置金额(' 1000 ');

订单映射器。插入(订单);

}

@事务性

@覆盖

public void child() {

订单Order=new Order();

秩序。setorderno(“child”);

秩序。设置状态(" 0 ");

秩序。settitle(' child ');

秩序。设置金额(' 2000 ');

订单映射器。插入(订单);

抛出新的运行时异常();

}

}

当调用父母方法时,会调用儿童方法,但执行完成后插入的记录有两条,一条是父母的,一条是儿童的;

这是因为上面的父母方法调用的儿童方法出现问题,@交易是基于面向切面编程的方式进行事务控制的(CglibAopProxy.java进行方法拦截,TransactionInterceptor.java进行代理对象调用执行方法),需要使用的是代理对象调用方法,上面的代码使用的还是这个,即当前实例化对象,因此执行this.child(),方法不能被拦截增强;

将上面的父母方法修改如下

@自动连线

私有应用程序上下文上下文;

private OrderService OrderService;

@PostConstruct

public void init() {

orderService=上下文。获取bean(orderService。类);

}

@事务性

@覆盖

public void parent() {

尝试{

//获取代理对象,通过代理对象调用子级()

订单服务。child();

//获取代理对象

//OrderService OrderService=(OrderService)AOP上下文。当前代理();

//orderservice。child();

} catch(异常e) {

log.error('插入异常,e);

}

订单Order=new Order();

秩序。setorderno(“parent”);

秩序。设置状态(" 0 ");

秩序。settitle(“父”);

秩序。设置金额(' 1000 ');

订单映射器。插入(订单);

}

执行父母方法,当出现异常的时候,事务会进行回滚;

如果想实现当调用父母方法时,调用儿童方法发生异常,只回滚儿童方法插入的数据,父方法插入的数据不回滚,修改如下

@事务性(传播=传播。需要_新)

@覆盖

public void child() {

订单Order=new Order();

秩序。setorderno(“child”);

秩序。设置状态(" 0 ");

秩序。settitle(' child ');

秩序。设置金额(' 2000 ');

订单映射器。插入(订单);

抛出新的运行时异常();

}

@事务性(传播=传播。需要_新)

如果当前存在事务,则挂起事务并开启一个新事务执行,新事务执行完毕后,唤醒之前的挂起的事务,则继续执行;如果当前不存在事务,则新建一个事务;

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: