配置Spring事务
- 首先需要引入命名空间:
tx - http://www.springframework.org/schema/tx
- 编写配置文件
<!-- mapper配置-->
<!-- 让 spring管理sqlsessionfactory使用mybatis和spring整合包中的 -->
<bean id="sqLSessionFactory" class="org.mybatis.spring.sqLsessionFactoryBean">
<!--数据库连接池-->
<property name="datasource" ref="dataSource" />
<!--加载mybatis的全局配置文件,虽然这个全局配置文件是空的,但是这个全局配置文件是必不可少的-->
<property name="configLocation" value="classpath:mybatis-config.xmL" />
<!--扫描sql配置文件:mapper需要的xml文件-->
<property name= "mapperLocations" value="classpath:mapper/*.xmL”/></bean>
<! --配置Mapper扫描器-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="edu.etime.sm.dao" />
</bean>
<!--配置事务管理-->
<!-- spring声明式事务管理控制,配置事务管理器类(注册事务管理器,将其注入到spring容器中)-->
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--事务管理器管理的数据源-->
<property name="dataSource" ref="dataSource" />
</bean>
<!--配置事务增强(如何管理事务,只读、读写...)-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name= "insert*" propagation="REQUIRED"/>
<tx:method name="delete*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="find*" propagation="SUPPORTS" read -only= "true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- aop配置,拦截哪些方法(切入点表达式,拦截上面的事务增强)-->
<aop:config>
<aop:pointcut id="pt" expression="execution( *edu.etime. sm.services.impl.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
</aop:config>
什么是事务?
-
事务(Transaction)是访问并可能更新数据库中各项数据项的一个程序执行单元(unit)。 事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
-
事务是一个不可分割的数据库操作序列,也是数据库并发控制的基本单位,其执行的结果必须使数据库从一种一致性状态变到另一种一致性状态。
-
事务结束有两种,事务中的步骤全部成功执行时,提交事务。如果其中一个失败,那么将会发生回滚操作,并且撤销之前的所有操作。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。
-
事务是恢复和并发控制的基本单位。
-
事务具有四个特征:原子性、一致性、隔离性和持久性。这四个特征通常称为ACID。
ACID四个关键属性
- 原子性( Atomicity ): 事务是一个原子操作,由一系列动作组成.事务的原子性确保动作要么全部完成要么完全不起作用.
- 一致性( Consistency ): 一旦所有事务动作完成,事务就被提交.数据和资源就处于一种满足业务规则的一致性状态中.
- 隔离性( Isolation ): 可能有许多事务会同时处理相同的数据,因此每个事物都应该与其他事务隔离开来,防止数据损坏.
- 持久性( Durability ): 一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响.通常情况下,事务的结果被写到持久化存储器中.
spring事务管理的7种传播行为
传播属性 | 描述 |
---|---|
REQUIRED | 如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行 |
REQUIRED_NEW | 当前的方法必须启动新事务,并在它自己的事务内运行.如果有事务正在运行,应该将它挂起 |
SUPPORTS | 如果有事务在运行,当前的方法就在这个事务内运行.否则它可以不运行在事务中. |
NOT_SUPPORTED | 当前的方法不应该运行在事务中.如果有运行的事务,将它挂起 |
MANDATORY | 当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常 |
NEVER | 当前的方法不应该运行在事务中.如果有运行的事务,就抛出异常 |
NESTED | 如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行.否则,就启动一个新的事务,并在它自己的事务内运行. |
并发事务所导致的问题可以分为下面三种类型:
-
脏读: 对于两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段.之后,若T2回滚,T1读取的内容就是临时且无效的.
-
不可重复读: 对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段.之后,T1再次读取同一个字段,值就不同了.
-
幻读: 对于两个事务T1,T2,T1 从一个表中读取了一个字段,然后T2在该表中插入了一些新的行.之后,如果T1再次读取同一个表,就会多出几行
事务隔离级别
隔离级别 | 描述 |
---|---|
DEFAULT | 使用底层数据库的默认隔离级别.对于大多数数据库来说,默认隔离级别都是READ_COMMITTED |
READ_UNCOMMITTED | 允许事务读取未被其他事物提交的变更.脏读,不可重复读和幻读的问题都会出现 |
READ_COMMITTED | 只允许事务读取已经被其它事务提交的变更.可以避免脏读,但不可重复读和幻读问题仍然可能出现 |
PEREATABLE_READ | 确保事务可以多次从-一个字段中读取相同的值.在这个事务持续期间,禁止其他事物对这个字段进行更新.可以避免脏读和不可重复读,但幻读的问题仍然存在. |
SERIALIZABLE | 确保事务可以从一个表中读取相同的行.在这个事务持续期问,禁止其他事务对该表执行插入,更新和删除操作.所有并发问题都可以避免,但性能十分低下. |
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
Read Uncommitted | YES | YES | YES |
Read Committed | NO | YES | YES |
Repeated Read | NO | NO | YES |
Serializable | NO | NO | NO |