一.编程式事务
二.声明式事务
整个事务操作由其他框架进行管理,我们想要使用只需要在程序中进行简单的配置/声明即可—-Spring Tx
在进行声明式事务的时候 一定注意不要自己捕获异常,一定要把异常抛出去,否则配置的声明式事务就不会在起作用
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<!--IOC+DI扫描-->
<context:component-scan base-package="com.bjsxt.service,com.bjsxt.pojo"></context:component-scan>
<!--引入属性文件-->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!--[1] 建立数据库连接-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${m_driver}"></property>
<property name="url" value="${m_url}"></property>
<property name="username" value="${m_username}"></property>
<property name="password" value="${m_password}"></property>
</bean>
<!--[2] 获取sqlsessionfactory对象-->
<bean id="factory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="typeAliasesPackage" value="com.bjsxt.pojo"></property>
</bean>
<!--[3] 扫描mapper文件-->
<bean id="mapper" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="sqlSessionFactoryBeanName" value="factory"></property>
<property name="basePackage" value="com.bjsxt.mapper"></property>
<!--自动创建了Peoplemapper Bean对象-->
</bean>
<bean id="accountService" class="com.bjsxt.service.impl.AccountServiceImpl">
<property name="accountMapper" ref="accountMapper"></property>
</bean>
<!--声明式事务的配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--配置事务通知-->
<tx:advice transaction-manager="transactionManager" id="tx" >
<tx:attributes>
<tx:method name="zq*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="pt1" expression="execution(* com.bjsxt.service.impl.*.*(..))"/>
<aop:advisor advice-ref="tx" pointcut-ref="pt1"></aop:advisor>
</aop:config>
</beans>
2.1声明式事务中属性解释:
[1] name
哪些方法需要有事务控制 支持*通配符
[2] readonly=”boolean”
是否是只读事务.
如果为true,告诉数据库此事务为只读事务.数据化优化,会对性能有一定提升,所以只要是查询的方法,建议使用此数据.不可以进行写操作
如果为false(默认值),事务需要提交的事务.建议新增,删除,修改.
[3]事务超时属性timeout(秒为单位)
timeout是设置超时属性。以秒为单位。当两秒钟时间内不能完成所有操作,就会抛异常。
spring进行事务管理中使用try-catch容器将不再管理事务。但是在catch中书写throw e将正常执行spring的事务管理
[4]rollback-for=”异常类型全限定路径”
- 当出现什么异常时需要进行回滚
- 建议:给定该属性值.
- 手动抛异常一定要给该属性值.
[5] no-rollback-for=””
当出现什么异常时不滚回事务.
三.控制事务传播行为
required:默认 如果当前有事务就在事务中执行,如果当前没有事务,新建一个事务。
supports:如果当前有事务就在事务中执行,如果当前没有事务,就在非事务下执行。
mandatory:必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错
requires_new:必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起
not_supported:必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前的事务挂起
never:必须在非事务状态下执行,如果当前没有事务,正常执行,如果当前有事务,报错
nested:必须在事务状态下执行,如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务(嵌套中的事务都执行)
四.事务隔离级别
4.1脏读
脏读就是指当事务A对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务B也访问了这个数据,然后使用了这个数据。(读取了没有提交到数据库中的数据)
4.2不可重复读
在事务1中,读取了一个数据,事务1还没有结束时,事务2也访问了这个数据,修改了这个数据,并提交,紧接着,事务1又读取数据。由于事务2的修改,那么事务1两次读到的数据可能是不一样的,因此称为不可重复读。
4.3幻读
当某个事务在读取某个范围的记录时,另外一个事务又在该范围插入了新的记录,当之前的事务再次读取该范围的记录时,产生幻行。InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。
注意:不可重复读和幻读的区别是:前者是指读到了已经提交的事务的更改数据(修改或删除),后者是指读到了其他已经提交事务的新增数据。
对于这两种问题解决采用不同的办法,防止读到更改数据,只需对操作的数据添加行级锁,防止操作中的数据发生变化;而防止读到新增数据,往往需要添加表级锁,将整张表锁定,防止新增数据(oracle采用多版本数据的方式实现)。
4.4隔离级别
- DEFAULT: 默认值,由底层数据库自动判断应该使用什么隔离界别
- READ_UNCOMMITTED: 可以读取未提交数据,可能出现脏读,不重复读,幻读. 效率最高.
- READ_COMMITTED:只能读取其他事务已提交数据.可以防止脏读,可能出现不可重复读和幻读.
- REPEATABLE_READ: 读取的数据被添加锁,防止其他事务修改此数据,可以防止不可重复读.脏读,可能出现幻读.
- SERIALIZABLE: 排队操作,对整个表添加锁.一个事务在操作数据时,另一个事务等待事务操作完成后才能操作这个表。最安全的 效率最低的。