如果不想看概念的话,直接跳到编程式事务管理(ctrl+F)那里开始
事务的四大特性:
原子性,一致性,隔离性,持久性
原子性是指事务是一个不可分割的工作单位,十五中的操作要么都发生,要么都不发生。
一致性是指事务前后数据的完整性必须保持一致。
隔离性是指多个用户并发访问数据库时,一个用户的食物不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离。
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对齐有任何影响。
Spring事务管理高层抽象主要包括3个接口
PlatformTransactionManager(事务管理器)
TransactionDefinition(事务定义信息[隔离,传播,超时,只读])
TransactionStatus(事务具体运行状态)
PlatformTransactionManager接口实现:
Org.springframework.jdbc.datasource.DataSourceTransactionManager(使用spring jdbc或ibatis进行持久化数据时使用)
Org.springframework.orm.hibernate3.HibernateTransactionManager(使用Hibernate3.0版本进行持久化数据)
Org.springframework.orm.jpa.JpaTransactionManager(使用JPA进行持久化时使用)
Org.springframework.jdo.JdoTransactionManager(当持久化机制是Jdo时使用)
Org.springframework.transaction.jta.JtaTransationManager(使用一个JTA实现来管理事务,在一个事务跨越多个资源时必须使用)
如果不考虑隔离性,会引发安全问题:
脏读,不可重复读,幻读
脏读:一个事务读取了另一个事务改写但还未提交的数据,如果这些数据被回滚,则读到的数据是无效的
不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同
幻读:一个事务读取了几行记录后,另一个事务插入一些记录,幻读就发生了,再后来的查询中,第一个事务就会发现有些原来没有的记录
事务隔离级别(四种)
Default(使用后端数据库默认的隔离级别)
READ_UNCOMMITED(允许你读取还未提交的改变了的数据。可能导致脏,幻,不可重复读)
READ_COMMITTED(允许在并发事务已经提交后读取,可防止脏读,但幻读和不可重复读仍会发生)
REPEATABLE_READ(对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏,不可重复读,但幻读扔可能发生)
SERIALIZABLE(完全服从ACID的隔离级别,确保不发生脏,幻,不可重复读,这在所有隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的)
PS:
Mysql默认采用REPEATABLE_READ隔离级别
Oracle默认采用READ_COMMITTED隔离级别
事务的传播行为(七种):
PROPAGATION_REQUIRED(支持当前事务,如果不存在,就新建一个)
PROPAGATION_SUPPORTS(支持当前事务,如果不存在,就不使用事务)
PROPAGATION_MANDATORY(支持当前事务,如果不存在,抛出异常)
PROPAGATION_REQUIRES_NEW(如果有事务存在,挂起当前事务,创建一个新的事务)
PROPAGATION_NOT_SUPPORTED(以非事务方式运行,如果有事务存在,挂起当前事务)
PROPAGATION_NEVER(以非事务方式运行,如果有事务存在,跑出异常)
PROPAGATION_NESTED(如果当前事务存在,则嵌套事务执行)
Spring支持两种方式事务管理
--编程式的事务管理(一种)
*在实际应用中很少使用
*通过TransactionTemplate手动管理事务
--使用XML配置声明式事务(三种)
*开发中推荐使用(代码入侵性最小)
*Spring的声明式事务是通过AOP实现的
编程式的事务管理:
Spring文件配置
<!--配置事务管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--配置事务管理的模板 -->
<bean id=”transactionTemplate” class=”org.springframework.transaction.support. TransactionTemplate”>
<property name=”transactionManager” ref=”transactionManager”/>
</bean>
<!--配置业务层类-->
<bean id=”accountService” class=”cn.muke.spring.demo1.AccountServiceImpl”>
<property name=”accountDao” ref=”accountDao”/>
<!--注入事务管理的模板 -->
<property name=”transactionTemplate” ref=”transactionTemplate”/>
</bean>
在业务实现类里面(serviceimpl):
//注入事务管理的模板:
Private TransactionTemplate transactionTemplate;
Public void transfer(String out,String in,double money){
TransactionTemplate.execute(new TransactionCallbackWithoutResult(){
Protected void doInTransactionWithoutResult(TransactionStatus transactionStatus){
AccountDao.outMoney(out,money);
Int i=1/0;
AccountDao.inMoney(in,money);
}
});
}
执行这个方法会失败,因为1/0会错误所以会回滚
声明式事务管理方式一:基于TransactionProxyFactoryBean的方式
Spring文件配置
<!--配置事务管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--配置业务层的代理-->
<bean id=”accountServiceProxy”class=”org.springframework.transaction.interceptor.TransactionProxyFactoryBean”>
<!--配置目标对象-->
<property name=”target” ref=”accountService”/>
<!--注入事务管理器 -->
<property name=”transactionManager” ref=”transactionManager”/>
<!--注入事务属性 -->
<property name=”transactionAttributes”>
<props>
<!--prop的格式:
*代表类中所有方法
*PROPAGATION :事务的传播行为
*ISOLATION:事务的隔离级别
*readOnly:只读(不可以进行插入,修改删除)
*-Exception:发生哪些异常回滚事务
*+Exception:发生哪些异常不回滚事务
-->
<prop key=”transfer”> PROPAGATION </prop>
</props>
</property>
</bean>
声明式事务管理方式二:基于AspectJ的XML方式
Spring文件配置
<!--配置事务管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--配置事务的通知:(事务的增强)-->
<tx:advice id=”txAdvice”transaction-manager=”transactionManager”>
<tx:attributes>
<!--
Propagation:事务传播行为
Isolation:事务隔离级别
Read-only:只读
Rollback-for:发生哪些异常回滚
No-rollback-for:发生哪些异常不会滚
Timeout”过期信息
-->
<tx:method name=”transfer” propagation=”REQUIRED”/>
</tx:attributes>
</ tx:advice >
<!--配置切面-->
<aop:config>
<!--配置切入点-->
<aop:pointcut expression=”execution(* cn.muke.spring.demo3.AccountService+.*(..))” id=”pointcut1”>
<!--配置切面-->
<aop:advisor advice-ref=”txAdvice” pointcut-ref=”pointcut1”/>
</aop:config>
声明式事务管理方式三:基于注解方式
Spring文件配置
<!--配置事务管理器 -->
<bean id=”transactionManager” class=”org.springframework.jdbc.datasource.DataSourceTransactionMnager”>
<property name=”dataSource” ref=”dataSource”/>
</bean>
<!--开启注解事务 -->
<tx:annotation-driven transaction-manager=”transactionManager”/>
在业务实现类里面(serviceimpl):
加上@Transactional即可
@Transactiona注解中的属性
Propagation:事务的传播行为
Isolation:事务的隔离级别
ReadOnly:只读
RollbackFor:发生哪些异常回滚
NoRollbackFor:发生哪些异常不回滚
例如:Transactiona(propagation=Propagation.REQUIRED,isolation=Isolation.Default)
总结:
--编程式的事务管理
*通过TransactionTemplate手动管理事务(很少使用)
--使用XML配置声明式事务
*基于TransactionProxyFactoryBean的方式(很少使用)
*需要为每个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强
*基于AspectJ的XML方式(经常使用)
*一旦配置好了,需要在类上加任何东西
*基于注解方式(经常使用)
*配置简单。需要在业务类上添加一个@Transactiona的注解