publicinterfaceTransactionDefinition{ 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; int PROPAGATION_NESTED = 6; int ISOLATION_DEFAULT = -1; int ISOLATION_READ_UNCOMMITTED = 1; // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED; int ISOLATION_READ_COMMITTED = 2; // same as java.sql.Connection.TRANSACTION_READ_COMMITTED; int ISOLATION_REPEATABLE_READ = 4; // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ; int ISOLATION_SERIALIZABLE = 8; // same as java.sql.Connection.TRANSACTION_SERIALIZABLE; int TIMEOUT_DEFAULT = -1;
While the Spring default behavior for declarative transaction management follows EJB convention (roll back is automatic only on unchecked exceptions), it is often useful to customize this behavior.
You can apply the @Transactional annotation to an interface definition, a method on an interface, a class definition, or a public method on a class. However, the mere presence of the @Transactional annotation is not enough to activate the transactional behavior. The @Transactional annotation is merely metadata that can be consumed by some runtime infrastructure that is @Transactional-aware and that can use the metadata to configure the appropriate beans with transactional behavior. In the preceding example, the <tx:annotation-driven/> element switches on the transactional behavior.
@EnableTransactionManagement and <tx:annotation-driven/> looks for @Transactional only on beans in the same application context in which they are defined. This means that, if you put annotation-driven configuration in a WebApplicationContext for a DispatcherServlet, it checks for @Transactional beans only in your controllers and not your services. See MVC for more information.
@EnableTransactionManagement and <tx:annotation-driven/> 只会在定义它们本身的上下文中寻找 @Transactional 注解的 bean, 如果是在 Web 应用的 DispatcherServlet 对应的 WebApplicationContext@EnableTransactionManagement and <tx:annotation-driven/>只会在这个上下文中查找,这个上下文一般只会定义控制器以及试图解析器等 web 组件,而不是 service 类。
In proxy mode (which is the default), only external method calls coming in through the proxy are intercepted. This means that self-invocation (in effect, a method within the target object calling another method of the target object) does not lead to an actual transaction at runtime even if the invoked method is marked with @Transactional. Also, the proxy must be fully initialized to provide the expected behavior, so you should not rely on this feature in your initialization code (that is, @PostConstruct).
由于 Spring 事务是基于代理的,只有通过代理的外部方法调用才会被拦截,目标对象内部的方法调用(一个方法调用对象内部的另一个方法)是不会在运行时导致一个实际的事务发生的;另外,必须完全初始化代理以提供预期的行为,因此不应在初始化代码(即@PostConstruct)中依赖此功能。
Consider using of AspectJ mode (see the mode attribute in the following table) if you expect self-invocations to be wrapped with transactions as well. In this case, there no proxy in the first place. Instead, the target class is woven (that is, its byte code is modified) to turn @Transactional into runtime behavior on any kind of method.
// single TransactionTemplate shared amongst all methods in this instance privatefinal TransactionTemplate transactionTemplate;
// use constructor-injection to supply the PlatformTransactionManager publicSimpleService(PlatformTransactionManager transactionManager){ this.transactionTemplate = new TransactionTemplate(transactionManager); }
public Object someServiceMethod(){ return transactionTemplate.execute(new TransactionCallback() { // the code in this method executes in a transactional context public Object doInTransaction(TransactionStatus status){ updateOperation1(); return resultOfUpdateOperation2(); } }); } }
也可以提直接使用 PlatformTransactionManager 来管理事务,需要结合 Spring 事务抽象的其它对象: TransactionDefinition, TransactionStatus。 可以实现事务的初始化、回滚和提交。编程式事务也可以显示设置事务的名称,声明式的事务名称一般都是默认的全限定类名+方法名。
Java
1 2 3 4 5 6 7 8 9 10 11 12 13 14
DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // explicitly setting the transaction name is something that can be done only programmatically def.setName("SomeTxName"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def); try { // execute your business logic here } catch (MyException ex) { txManager.rollback(status); throw ex; } txManager.commit(status);
Do not call rollback on a transaction if commit threw an exception. The transaction will already have been completed and cleaned up when commit returns, even in case of a commit exception. Consequently, a rollback call after commit failure will lead to an IllegalTransactionStateException.