1. REQUIRED(默认):
Support a current transaction, create a new one if none exists.
支持当前事务,如果没有则创建一个新的
2. SUPPORTS
Support a current transaction, execute non-transactionally if none exists.
支持当前事务,如果没有则不使用事务
3. MANDATORY
Support a current transaction, throw an exception if none exists
支持当前事务,如果没有事务则报错
4. REQUIRED_NEW
Create a new transaction, and suspend the current transaction if one exists.
新建一个事务,同时将当前事务挂起
5. NOT_SUPPORTED
Execute non-transactionally, suspend the current transaction if one exists
以无事务的方式执行,如果当前有事务则将其挂起
6. NEVER
Execute non-transactionally, throw an exception if a transaction exists.
以无事务的方式执行,如果当前有事务则报错
7. NESTED
Execute within a nested transaction if a current transaction exists,behave like PROPAGATION_REQUIRED else
如果当前有事务,则在当前事务内部嵌套一个事务,内部事务的回滚不影响当前事务。如果当前没有事务,就相当于REQUIRED
Note: Actual creation of a nested transaction will only work on specific transaction managers. Out of the box, this only applies to
the JDBC DataSourceTransactionManager when working on a JDBC 3.0 driver.
Some JTA providers might support nested transactions as well.
注意:该定义只能在JDBC3.0驱动下的DataSourceTransactionManager事务管理器中使用,有些JTA事务可能也会支持
@Transactional(propagation = Propagation.NEVER)
public User findById(Long id) {
User user = userMapper.findById(id);
System.out.println("find user:"+user);
return user;
}
@Transactional
public void transactionTest(int t) {
findById(t+0L);
}
我们调用transactionTest方法,transactionTest没有配置Propagation,所以默认是REQUIRED,会在当前新建一个事务。transactionTest内部调用findById,由于findById事务传播定义为NEVER,表明它当前不能有事务,按理说这里会抛出异常,但是我们利用junit执行后发现,transactionTest是可以正常执行的。
事实上,如果使用@Transaction方法里嵌套调用的是同一个类的方法,spring代理会忽略嵌套方法的@Transaction配置。但是,如果是其他注入对象的方法,那么@Transaction配置就会生效。我们将上面的transactionTest方法的事务传播定义为NERVER,并新增一个insert操作,即使insert启用了事务并且抛出异常,但是事务不会生效,也不会有回滚的说法,程序会抛出异常但是数据会保存到数据库中:
@Transactional(propagation = Propagation.NEVER)
public void transactionTest(int t) {
findById(t+0L);
insertUser("huangxl","abc123");
}
@Transactional
public int insertUser(String name, String password) {
User user = new User();
user.setPassword(password);
user.setUsername(name);
int insertCount = userMapper.insertEntity(user);
if(insertCount == 1 ){
throw new RuntimeException("test transaction roll back");
}
return insertCount;
}
一、Propagation.NERVER的测试
下面我们将UserService注入到TransactionTestServiceImpl中,test方法使用@Transactional,UserService findById事务传播定义不变,还是NERVER。
UserserviceImpl:
@Service
public class TransactionTestServiceImpl implements TransactionTestService {
@Autowired
private UserService userService;
@Override
@Transactional
public void test() {
userService.findById(1L);
}
}
TransactionTestServiceImpl:
@Service
public class UserServiceImpl implements UserService {
@Override
@Transactional(propagation = Propagation.NEVER)
public User findById(Long id) {
User user = userMapper.findById(id);
System.out.println("find user:"+user);
return user;
}
}
由于test默认启用了事务,findById不允许当前有事务,所以我们执行test方法后会发现程序抛出了异常:
org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation ‘never’
二、Propagation.REQUIRED的测试
UserserviceImpl:
@Transactional
public int insertUser(String name, String password) {
User user = new User();
user.setPassword(password);
user.setUsername(name);
int insertCount = userMapper.insertEntity(user);
if(insertCount == 1 ){
throw new RuntimeException("test transaction roll back");
}
return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
try {
userService.insertUser("abc", "123");
} catch (Exception e) {
//do Nothing
}
userMapper.updateUserPassWord(1L, "456");
}
我们会发现,即使捕获了userService.insertUser抛出的异常,test还是把insertUser和updateUserPassword操作当成是一个整体,整个事务还是回滚了,程序抛出了下面的异常:
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
三、Propagation.NESTED的测试
UserserviceImpl:
@Transactional(propagation = Propagation.NESTED)
public int insertUser(String name, String password) {
User user = new User();
user.setPassword(password);
user.setUsername(name);
int insertCount = userMapper.insertEntity(user);
if(insertCount == 1 ){
throw new RuntimeException("test transaction roll back");
}
return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
try {
userService.insertUser("abc", "123");
} catch (Exception e) {
//do Nothing
}
userMapper.updateUserPassWord(1L, "456");
}
程序正常运行,因为NESTED内部事务回滚不影响外部事务。假如这个时候我们把test的@Transactional去掉再运行test方法,发现insertUser没有插入用户信息,说明当前没有事务的情况下,NESTED会默认创建一个事务,类似于REQUIRED。
如果我们把程序改为下面的情况:
UserserviceImpl:
@Transactional(propagation = Propagation.NESTED)
public int insertUser(String name, String password) {
User user = new User();
user.setPassword(password);
user.setUsername(name);
int insertCount = userMapper.insertEntity(user);
return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
userService.insertUser("abc", "123");
int updateRow = userMapper.updateUserPassWord(1L, "456");
if (updateRow == 1) {
throw new RuntimeException("transational roll back");
}
}
我们会发现没有插入用户信息,当前事务和子事务全部回滚。
四、Propagation.REQUIRED_NEW的测试
UserserviceImpl:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int insertUser(String name, String password) {
User user = new User();
user.setPassword(password);
user.setUsername(name);
int insertCount = userMapper.insertEntity(user);
return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
userService.insertUser("abc", "123");
int updateRow = userMapper.updateUserPassWord(1L, "456");
if (updateRow == 1) {
throw new RuntimeException("transational roll back");
}
}
运行结果:程序报错,但是有用户信息插入。
将程序改为下面的样子:
UserserviceImpl:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int updateUserPassWorld(Long id, String password) {
int update = userMapper.updateUserPassWord(id,password);
return update;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
//当前事务
userMapper.updateUserPassWord(28L, "123456");
//执行REQUIRES_NEW事务
userService.updateUserPassWorld(28L, "000000");
System.out.println("commit");
}
执行程序,发现程序迟迟没有打印字符串commit,发生了死锁。
五、NOT_SUPPORTED的测试
UserserviceImpl:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public int updateUserPassWorld(Long id, String password) {
int updateRow = userMapper.updateUserPassWord(id,password);
if(updateRow ==1 ){
throw new RuntimeException("roll back test");
}
return updateRow;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
userService.updateUserPassWorld(28L, "000000");
}
程序运行报错,但是id为28的用户密码还是更新了。
UserserviceImpl:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public int updateUserPassWorld(Long id, String password) {
int update = userMapper.updateUserPassWord(id,password);
return update;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
//当前事务
userMapper.updateUserPassWord(28L, "123456");
//执行REQUIRES_NEW事务
userService.updateUserPassWorld(28L, "000000");
System.out.println("commit");
}
执行程序,发现程序迟迟没有打印字符串commit,发生了死锁。
六、NOT_SUPPORTED的测试
UserserviceImpl:
@Transactional(propagation = Propagation.MANDATORY)
public int updateUserPassWorld(Long id, String password) {
int updateRow = userMapper.updateUserPassWord(id,password);
return updateRow;
}
TransactionTestServiceImpl:
public void test() {
userService.updateUserPassWorld(28L, "123456");
}
程序运行错误:
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation ‘mandatory’
我发现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.
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
我有一个涉及多台机器、消息队列和事务的问题。因此,例如用户点击网页,点击将消息发送到另一台机器,该机器将付款添加到用户的帐户。每秒可能有数千次点击。事务的所有方面都应该是容错的。我以前从未遇到过这样的事情,但一些阅读表明这是一个众所周知的问题。所以我的问题。我假设安全的方法是使用两阶段提交,但协议(protocol)是阻塞的,所以我不会获得所需的性能,我是否正确?我通常写Ruby,但似乎Redis之类的数据库和Rescue、RabbitMQ等消息队列系统对我的帮助不大——即使我实现某种两阶段提交,如果Redis崩溃,数据也会丢失,因为它本质上只是内存。所有这些让我开始关注erlang和
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
转自:spring.profiles.active和spring.profiles.include的使用及区别说明下文笔者讲述spring.profiles.active和spring.profiles.include的区别简介说明,如下所示我们都知道,在日常开发中,开发|测试|生产环境都拥有不同的配置信息如:jdbc地址、ip、端口等此时为了避免每次都修改全部信息,我们则可以采用以上的属性处理此类异常spring.profiles.active属性例:配置文件,可使用以下方式定义application-${profile}.properties开发环境配置文件:application-dev
这是我的网络应用:classFront我是这样开始的(请不要建议使用Rack):Front.start!这是我的Puma配置对象,我不知道如何传递给它:require'puma/configuration'Puma::Configuration.new({log_requests:true,debug:true})说真的,怎么样? 最佳答案 配置与您运行的方式紧密相关puma服务器。运行的标准方式puma-pumaCLI命令。为了配置puma配置文件config/puma.rb或config/puma/.rb应该提供(参见examp
我有一个电子邮件表格。但是我正在制作一个测试电子邮件表单,用户可以在其中添加一个唯一的电子邮件,并让电子邮件测试将其发送到该特定电子邮件。为了简单起见,我决定让测试电子邮件通过ajax执行,并将整个内容粘贴到另一个电子邮件表单中。我不知道如何将变量从我的HAML发送到我的Controllernew.html.haml-form_tagadmin_email_blast_pathdoSubject%br=text_field_tag'subject',:class=>"mass_email_subject"%brBody%br=text_area_tag'message','',:nam
我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi