Spring声明式事务
1.回顾事务
事务四大特性(ACID):
1.原子性->要么都成功执行,要么都失败
2.一致性->事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态
3.隔离性->隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离
4.持久性->持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作
2.Spring中的事务管理
使用原因:当一个事务中对数据库进行删,增操作如:
此时如果删除操作的出现代码错误,则add执行,delete操作不执行,这违反了事务的原子性,我们希望它两个操作要么都成功,要么都不成功,因此使用spring的事务管理进行管理。
2.1声明式事务->实质为AOP的应用
2.1.1.开启spring的事务处理功能(与数据库相关写在spring-dao.xml中)
<!--配置声明式事务-->
<!--1.开启Spring事务处理功能-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
2.2.2修改头文件约束,引入tx标签
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
2.2.3设置管理器,并结合AOP进行事务的织入
<!--结合AOP进行事务的织入-->
<!--配置事务通知
参数:
id:任取
transaction-manager:事务管理器 唯一,由spring提供
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<tx:attributes>
<!--给所有的add,delete方法配置事务,填*为所有方法-->
<!--可配置事务的传播特性 timeout超时 rollback-for回滚......,不写则默认propagation="REQUIRED"
REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
-->
<!-- <tx:method name="add"/>-->
<!-- <tx:method name="delete" timeout="-1" />-->
<tx:method name="*"></tx:method>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<!--切入点com.hong.mapper下所有类所有方法-->
<aop:pointcut id="pointcut" expression="execution(* com.hong.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
</beans>
2.2.4总体
<?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:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- DataSource数据源 :使用Spring的数据源替换Mybatis的位置
参数:class->使用spring提供的JDBC org.springframework.jdbc.datasource.DriverManagerDataSource (导入spring-mybatis整合包才会有)-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<!--配置相应参数,与db.properties中相同-->
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf8"></property>
<property name="username" value="root"></property>
<property name="password" value="long123"></property>
</bean>
<!-- sqlSessionFactory 可在官网上直接复制-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--在这绑定MyBatis的配置文件 value为文件位置-->
<property name="configLocation" value="classpath:mybatis-config.xml"></property>
<!--也可以将mybatis-config中的配置写在这,例如这扫描注册Mapper包,*代表所有文件-->
<property name="mapperLocations" value="classpath:com/hong/mapper/*.xml"></property>
</bean>
<!--sqlSession的设置 在spring中把sqlSession变为sqlSessionTemplate,但在取id时仍然可以成为sqlSession,sqlSessionTemplate为线程安全的-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--注入参数sqlSessionFactory,在源码中它只有构造器注入-->
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!--配置声明式事务-->
<!--1.开启Spring事务处理功能-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<!--结合AOP进行事务的织入-->
<!--配置事务通知
参数:
id:任取
transaction-manager:事务管理器 唯一由spring提供
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--给哪些方法配置事务-->
<tx:attributes>
<!--给所有的add,delete方法配置事务,填*为所有方法-->
<!--可配置事务的传播特性 timeout超时 rollback-for回滚......,不写则默认propagation="REQUIRED"-->
<!-- <tx:method name="add"/>-->
<!-- <tx:method name="delete" timeout="-1" />-->
<tx:method name="*"></tx:method>
</tx:attributes>
</tx:advice>
<!--配置事务切入-->
<aop:config>
<!--切入点com.hong.mapper下所有类所有方法-->
<aop:pointcut id="pointcut" expression="execution(* com.hong.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut"></aop:advisor>
</aop:config>
</beans>
2.2编程式事务->需要在代码中进行事务的管理->使用try{}catch{}包围,在catch中使用rollback等操作来管理