Spring和JTA的@Transactional标记
总体而言,Spring的@Transactional比JTA的@Transactional要强大和更灵活。
@javax.transaction.Transactional,可以配置参数:
- dontRollbackOn:不触发回滚的异常黑名单
- roolbackOn:异常白名单将覆盖缺省的rollback规则
- value:什么时候和如何创建transaction,值为Transactional.TxType的enum,如下,缺省为REQUIRED。
- MANDATORY:transaction必须存在,不会创建新的,如果没有,抛出异常
- NEVER:transaction必须不存在,否则抛出异常
- NOT_SUPPORTED:transaction没有被使用,如果已经存在,将被挂起,代码在事务外运行,完成后,事务继续。
- REQUIRED:transaction必须被使用,如果不存在,将在方法前开始创建,并在方法返回时结束。如果已经存在,则是使用之。
- REQUIRES_NEW:如果不存在,将在方法前开始,并在方法返回时结束,如果存在,则原transaction被挂起,开启新的transaction,并在方法结束是,结束新的transaction,继续执行原事务。
- SUPPORTS:如果已经有transaction,则使用之,如果没有,则不使用事务执行代码。
@org.springframework.transaction.annotation.Transactional使用:
- noRollbackFor 等同@javax.transaction.Transactional的dontRollbackOn
- rollbackFor 等同@javax.transaction.Transactional的rollbackOn
- propagation 等同@javax.transaction.Transactional的value,enum同Transactional.TxType的enum,缺省值都是REQUIRED。此外增加了
- NESTED:如果不存在,创建一个新的事务,如果存在,创建一个nested事务。JpaTransactionManager不支持NESTED,只被某些JpaTransactionManager提供者提供的JpaTransactionManager所支持,因此不具有可移植性。
- noRollbackForClassName
- rollbackForClassName
- isolation:设置isolation等级,使用org.springframework.transaction.annotation.Isolation enum,有NONE, READ_COMMITTED, READ_UNCOMMITTED,REPEATABLE_READ和SERIALIZABLE,如无特殊,我们可以使用READ_COMMITTED。但是JpaTransactionManager和JtaTransactionManager都不支持对事务的isolation等级,会忽略该参数,它们将采用JPA或者JTA DataSource的isolation等级,如果没有,则使用JDBC的限制等级。
- readOnly:但JpaTransactionManager和JtaTransactionManager均不支持,不允许写。
- timeout:JtaTransactionManager,但JpaTransactionManager不支持,限定transaction的执行时间(不含rollback)。
@Transactional可以标记接口或其方法,类或其方法。建议标记在类获取方法。如果标记在接口,只有允许动态proxy(即proxyTargetClass = false)时才有效。而且事务应是具体实现,而不是在接口契约的限制(和validate不同)
Service中使用事务的小例子
@Service
public class DefaultBookManager implements BookManager {
@Inject AuthorRepository authorRepository;
@Inject BookRepository bookRepository;
@Inject PublisherRepository publisherRepository;
/*【注意】如果我们不标记为@Transactional,在写操作中会出现nested exception is javax.persistence.
* TransactionRequiredException: No EntityManager with actual transaction available for current thread -
* cannot reliably process 'persist' call的异常。这是获取EntityManager出错,获取是从SharedEntityManagerBean
*中获得,可能和isolation的等级有关。纯读的操作没有问题。*/
@Override
@Transactional
public List<Author> getAuthors() {
return this.toList(authorRepository.getAll());
}
@Override
@Transactional
public void saveAuthor(Author author) {
if(author.getId() < 1)
this.authorRepository.add(author);
else
this.authorRepository.update(author);
}
......
}
相关链接: 我的Professional Java for Web Applications相关文章