Spring事务传播行为体现在某个service方法调用另一个service方法,事务该如何进行下去。
Spring支持7中事务传播方式,在Propagation类中可以看到,如下:
REQUIRED(0), SUPPORTS(1), MANDATORY(2), REQUIRES_NEW(3), NOT_SUPPORTED(4), NEVER(5), NESTED(6);
使用方式就是在service方法上加入Transational注解,例如:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
下面逐个介绍下这7中事务传播方式:
1. REQUIRED:
Spring的默认事务传播方式。从字面意思看,它表示此枚举修饰的service方法必须运行在一个事务中,如果当前存在一个事务(比如其他有事务的service方法调用此方法),则运行在当前事务中,否则开启一个新的事务。
示例代码如下:
注意:这里methodA调用methodB必须要用Spring的代理方式,即用testService.methodB()方式调用,如果只是method()方式调用则相当于this.methodB()在本对象中调用,事务不起作用的,一定要是Spring的AOP代理。@Lazy注解是为了防止启动的时候出现循环依赖报错,采用懒加载方式注入Bean。
下面示例中,methodA调用methodB的时候,会先开启一个事务,methodB中会使用methodA这个事务,和methodA一起提交或回滚。
@Service
public class TestServiceImpl implements TestService {
@Resource @Lazy
private TestService testService;
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
}
2. SUPPORTS:
从字面意思看,它是支持的意思,也就是有事务我也支持,没有也行。
即:调用此方法时如果有一个事务,那么就在当前事务中执行,和当前事务一起提交或回滚。如果当前没有事务,那么就不开启事务,在无事务环境中执行。
下面示例代码中,methodB是SUPPORTS事务传播方式,methodB有没有事务取决于调用它的methodA。可以看到此时methodA是有一个事务的,所以methodB会在methodA这个事务中一起提交或回滚。
@Service
public class TestServiceImpl implements TestService {
@Resource @Lazy
private TestService testService;
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
}
3. MANDATORY:
字面意思:强制。
没错,就是一定要在事务中执行,否则就会抛异常。
如下面的代码,如果直接调用methodB,由于当前没有事务,会抛出一个IllegalTransactionStateException异常。如果是在methodA中调用methodB,由于methodA开启了一个事务,所以methodB会在methodA的事务中执行,不会报错。
@Service
public class TestServiceImpl implements TestService {
@Resource @Lazy
private TestService testService;
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.MANDATORY)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
}
4. REQUIRES_NEW:
字面意思:开启一个新的事务。
这个事务传播方式会挂起当前事务,开启一个新的事务,方法会在新的事务中执行并提交,提交完之后,挂起的事务继续往下走。
如下代码,methodA调用methodB的时候,当前事务会被挂起,然后在methodB中会开启一个新的事务,methodB执行完并且事务提交后,methodA的事务继续执行。methodB回滚不影响methodA,methodA回滚也不影响methodB。
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
5. NOT_SUPPORTED:
字面意思:不支持事务。
用该枚举修饰的方法一定会运行在非事务环境中,即使调用此方法时有一个事务,也会将该事务挂起。我们通常将这种方式应用于强制要求非事务的方法中,例如我们现在要将批量数据去集成第三方接口然后更新状态到DB,不能说某一个数据出错就导致所有数据状态都回滚,那样的话,已经成功集成过第三方接口的数据就又得重新去集成了,会造成重复调用,导致第三方系统中的数据混乱。
如下代码,methodA有一个事务,当它调用methodB时,事务会被挂起,然后methodB中的CRUD操作不会在事务中执行,会立即提交到数据库。methodB执行完之后,methodA的事务继续进行,methodA的回滚不影响methodB。
@Transactional
@Override
public void methodA() {
testService.methodB();
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.NOT_SUPPORTED)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
}
6. NEVER:
字面意思:永远也不在事务中运行。
该枚举修饰的方法一旦在事务环境中就会抛异常。
7. NESTED:
字面意思:嵌套事务。
这种传播方式稍微有点复杂,目前各种厂商对它的支持可能存在差异,需要看具体的事务管理实现方式。
用此枚举修饰的方法,当外部有事务的时候,会在里面嵌套一个事务,里面的事务回滚不会影响外部事务,但外部事务出错回滚会将里面的也一起回滚。
如下methodB会在methodA的事务里面再嵌套一个事务,当methodA事务提交,methodB也会跟着一起提交,当methodA出错回滚,会把methodB也一起回滚。当methodB出错回滚,不会影响methodA的事务,事务会回退到调用methodB前的节点,然后继续处理后续的步骤。
@Transactional
@Override
public void methodA() {
System.out.println("CRUD operation in methodA before...");
//保存当前状态,开启嵌套事务
try {
testService.methodB();
} catch (Exception e) {
e.printStackTrace();
}
//methodB回滚后不影响methodA事务继续进行
System.out.println("CRUD operation in methodA...");
}
@Transactional(propagation = Propagation.NESTED)
@Override
public void methodB() {
System.out.println("CRUD operation in methodB...");
throw new RuntimeException("methodB rollback");
}

我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的
我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.
question的一些答案关于redirect_to让我想到了其他一些问题。基本上,我正在使用Rails2.1编写博客应用程序。我一直在尝试自己完成大部分工作(因为我对Rails有所了解),但在需要时会引用Internet上的教程和引用资料。我设法让一个简单的博客正常运行,然后我尝试添加评论。靠我自己,我设法让它进入了可以从script/console添加评论的阶段,但我无法让表单正常工作。我遵循的其中一个教程建议在帖子Controller中创建一个“评论”操作,以添加评论。我的问题是:这是“标准”方式吗?我的另一个问题的答案之一似乎暗示应该有一个CommentsController参
我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
这是针对我无法破坏的现有公共(public)API,但我确实希望对其进行扩展。目前,该方法采用字符串或符号或任何其他在作为第一个参数传递给send时有意义的内容我想添加发送字符串、符号等列表的功能。我可以只使用is_a吗?数组,但还有其他发送列表的方法,这不是很像ruby。我将调用列表中的map,所以第一个倾向是使用respond_to?:map。但是字符串也会响应:map,所以这行不通。 最佳答案 如何将它们全部视为数组?String的行为与仅包含String的Array相同:deffoo(obj,arg)[*arg].eac