我写了
public class DefaultFooService implements FooService {
@Transactional(propagation=Propagation.REQUIRED)
getFoo("a", "a");
throw new UnsupportedOperationException();
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void getFoo(String fooName, String barName) {
throw new UnsupportedOperationException();
}
}
然后测试
public class Boot {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("context.xml", Boot.class);
FooService fooService = (FooService) ctx.getBean("fooService");
try {
fooService.getFoo("d");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
却方法显示的是
10:41:40,128 DEBUG main datasource.DataSourceTransactionManager:371 - Creating new transaction with name [x.y.service.FooService.getFoo]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
10:41:40,458 DEBUG main datasource.DataSourceTransactionManager:202 - Acquired Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] for JDBC transaction
10:41:40,458 DEBUG main datasource.DataSourceTransactionManager:219 - Switching JDBC Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] to manual commit
10:41:40,458 DEBUG main datasource.DataSourceTransactionManager:821 - Initiating transaction rollback
10:41:40,468 DEBUG main datasource.DataSourceTransactionManager:273 - Rolling back JDBC transaction on Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver]
10:41:40,468 DEBUG main datasource.DataSourceTransactionManager:314 - Releasing JDBC Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] after transaction
发现只create 一个 transaction,而propagation=Propagation.REQUIRED_NEW并没起作用
之后文档查出
The key thing to understand here is that the client code inside the main(..) of the Main class has a reference to the proxy. This means that method calls on that object reference will be calls on the proxy, and as such the proxy will be able to delegate to all of the interceptors (advice) that are relevant to that particular method call.However, once the call has finally reached the target object, theSimplePojo reference in this case, any method calls that it may make on itself, such asthis.bar() orthis.foo(), are going to be invoked against thethis reference, andnot the proxy. This has important implications. It means that self-invocation isnot going to result in the advice associated with a method invocation getting a chance to execute.
就是说一旦调用最后到达了目标对象,比如咱们调用的fooService对象,任何方法调用是用它自己的对象,而不是代理,最重要的含义是,意味着自身的调用不会引起关联该方法调用的advice获得一个执行的机会,也就是说当fooService.getFoo("d");自身调用了getFoo("a", "a");transaction的advice不会再执行了,所以propagation=Propagation.REQUIRED_NEW不起作用了。
于是我改成了
public class DefaultFooService implements FooService {
private DefaultFooService2 fooService2;
public void setFooService2(DefaultFooService2 fooService2) {
this.fooService2 = fooService2;
}
@Transactional(propagation=Propagation.REQUIRED)
public void getFoo(String fooName){
//fooService2.getFoo("d", "ff");
fooService2.getFoo("d", "dd");
throw new UnsupportedOperationException();
}
public class DefaultFooService2 {
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void getFoo(String fooName, String barName) {
// throw new UnsupportedOperationException();
}
}
<bean id="fooService" class="x.y.service.DefaultFooService">
<property name="fooService2" ref="fooService2"/>
</bean>
<bean id="fooService2" class="x.y.service.DefaultFooService2"/>
结果显示为
1:08:46,927 DEBUG main datasource.DataSourceTransactionManager:371 - Creating new transaction with name [x.y.service.FooService.getFoo]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
11:08:47,257 DEBUG main datasource.DataSourceTransactionManager:202 - Acquired Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] for JDBC transaction
11:08:47,257 DEBUG main datasource.DataSourceTransactionManager:219 - Switching JDBC Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] to manual commit
11:08:47,257 DEBUG main datasource.DataSourceTransactionManager:419 - Suspending current transaction, creating new transaction with name [x.y.service.DefaultFooService2.getFoo]
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:202 - Acquired Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] for JDBC transaction
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:219 - Switching JDBC Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] to manual commit
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:730 - Initiating transaction commit
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:259 - Committing JDBC transaction on Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver]
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:314 - Releasing JDBC Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] after transaction
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:993 - Resuming suspended transaction
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:821 - Initiating transaction rollback
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:273 - Rolling back JDBC transaction on Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver]
11:08:47,278 DEBUG main datasource.DataSourceTransactionManager:314 - Releasing JDBC Connection [jdbc:oracle:thin:@localhost:1521:orcl, UserName=SCOTT, Oracle JDBC driver] after transaction
确实创建了2个transaction
如何显示debug信息请看
Showing a Spring transaction in log4j
参考:
http://stackoverflow.com/questions/15767914/strange-behaviour-with-transactionalpropagation-propagation-requires-new/15769398#15769398
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/htmlsingle/#aop-understanding-aop-proxies