Spring 支持编程式事务和声明是事务处理。 编程式事务管理通过在业务方法中嵌入控制事务提交和回滚的事务管理代码来实现。 声明式事务管理时通过AOP框架支持的。
Spring 核心事务管理抽象基于PlatformTransactionManager接口。它封装了一组用户事务管理的技术独立方法。TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
Spring 对这个接口提供了多种内建实现:
JtaTransactionManager
JmsTransactionManager
JpaTransactionManager
JdoTransactionManager
HibernateTransactionManager
DataSourceTransactionManager
Spring 事务的传播属性有”
REQUIRED: 如果现有事务正在运行,当前方法应该在事务中运行,否则它将启动新的事务,并在自己的事务中运行。
REQUIRES_NEW:当前方法必须启动新事务,并在自己的事务中运行;如果现有的事务正在运行,它将被挂起。
SUPPORTS:如果现有事务重在运行,当前方法应该运行在事务中,否则它没有必要运行在事务中。
NOT_SUPPORTED:当前方法不应该运行在事务中,如果现有事务正在运行则,它将被挂起
MANDATORY:当前方法必须运行在一个事务中,如果没有事务在进行中,它将抛出一个异常;
NEVER:当前方法不应该运行在事务中,如果现有事务正在运行中,将抛出一个异常。
NESTED:如果现有事务正在运行,当前方法应该运行在嵌套事务中,否则,它应该启动一个新的事务并运行在自己的事务中。这个功能时Spring 特有的。该行为对批处理特别有用。
事务的隔离:
事务的隔离是由底层数据库引擎实现的而不是Spring 框架实现的。
DEFAULT: 使用底层数据库默认的隔离级别。对于大多数数据库而言,默认的隔离级别是READ_COMMITTED;
READ_UNCOMMITTED: 允许读取其他事务未提交的修改
READ_COMMITTED:运行读取其他事务提交的修改
REPEATABLE_READ:确保事务能够多次从一个字段中读取到同一个值。在本事务期间,其他事务更细被禁止。
SERIALIZABLE:确保一个事务从表中多次读取相同的行。在事务期间,其他事务对该表的插入,更新,删除将全部被禁止。
编程式事务管理:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd "> <context:component-scan base-package="com.david.*" /> <aop:aspectj-autoproxy /> <!-- 定义jdbc模板类 --> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 事务模板 --> <bean id="transactionTemlate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" /> <bean class="org.springframework.validation.beanvalidation.BeanValidationPostProcessor" /> <!-- 方法验证后处理器 --> <bean class="org.springframework.validation.beanvalidation.MethodValidationPostProcessor" /> </beans>
/** * @see com.david.biz.service.BookService#addBook(com.david.common.domain.Book) */ public boolean addBook(final Book book) throws Exception { transactionTemplate.execute(new TransactionCallback<Boolean>() { public Boolean doInTransaction(TransactionStatus status) { try { bookDao.insert(book); return Boolean.TRUE; } catch (Exception e) { // rollback status.setRollbackOnly(); } return Boolean.FALSE; } }); }
使用声明式事务管理:
/** * * @see com.david.biz.service.BookService#addBook() */ @Transactional(propagation = Propagation.REQUIRED) public void addBook(Book book) throws Exception { bookDao.insert(book); throw new UnRollbackException("受检查异常是不会回滚事务的"); }
默认情况下,只有非受控异常也就是RuntimerException 和Error类型的异常将导致事务回滚,而受控异常则不会回滚。但是可以通过设置rollbackFor 和noRollbackFor属性处理受控异常的回滚。
public class AService{ private BService b; @Transactional(propagation = Propagation.REQUIRED) public void aMethod(){ b.bmethod(); } } public class BService{ @Transactional(propagation = Propagation.REQUIRED) public void bMethod(){ } }
如果事务的传播属性是REQUIRED, 如果b的事务已经提交后,在a中发生异常则会连同b一起回滚,因为这个两个使用的是同一个事务。
如果事务的传播属性是REQUIRES_NEW, 则a 中发生异常不会响应到b的事务提交,因为b和a是两个不同的是事务