spring事务 深入理解spring事务
徘徊在深夜中的猫 人气:0想了解深入理解spring事务的相关内容吗,徘徊在深夜中的猫在本文为您仔细讲解spring事务的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:spring事务使用,spring事务操作,下面大家一起来学习吧。
事务介绍
一个事务要么同时成功,要么同时失败
特性
- Atomic原子性 事务是由一个或多个活动组成的一个工作单元。原子性确保事务中的所有操作全部发生或全部不发生
- Consistent一致性 一旦事务完成,系统必须确保它所建模的业务处于一致的状态
- Isolated隔离性 事务允许多个用户对数据进行操作,每个用户的操作不会与其他用户纠缠在一起
- Durable持久性 一旦事务完成,事务的结果应该持久化
事务隔离级别
- DEFAULT 使用底层数据库预设的隔离层级
- READ_UNCOMMITTED (读未提交的数据) 允许事务读取其他并行的事务还没提交的数据,脏读、不可重复读、幻读问题都存在
- READ_COMMITTED(读已提交的数据) 只允许事务读取其他并行事务提交的数据,可以避免脏读,但是不可重复读和幻读仍存在
- REPEATABLE_READ(可重复读) 确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新,可以避免脏读和不可重复读,但幻读仍存在(Mysql默认的事务隔离级别)
- SERIALIZABLE(串行化) 确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可以避免,但是性能低下
传播行为
- PROPAGATION_REQUIRED 支持当前事务,如果当前没有事务,就新建一个事务
- PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行
- PROPAGATION_MANDATORY 支持当前事务,如果当前没有事务,就抛出异常
- PROPAGATION_REQUIRED_NEW 新建事务,如果当前存在事务,把当前事务挂起
- PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
- PROPAGATION_NEVER 以非事务方式执行操作,如果当前存在事务,则抛出异常
- PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则新建事务
只读
事务只进行读取操作
readOnly=true 告诉spring当前事务只会进行读取操作,不会进行修改操作,可以帮助数据库引擎优化
注:如果设置为只读的话,千万不要在事务里修改数据,使用只读操作时,spring不会进行加锁处理,如果修改数据的话,会出现问题
事务超时
事务时间过长,则回滚
回滚规则
rollback-for 指事务对于那些检查型异常应当回滚而不提交(默认spring会对所有的运行时异常回滚)
no-rollback-for 指事务对于那些异常继续执行不回滚
事务的使用
create table user( id int primary key AUTO_INCREMENT, name varchar(20) not null, account double )ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into user (name,account) values('张三',1000); insert into user (name,account) values('李四',1000);
<!-- 事务 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>4.3.29.RELEASE</version> </dependency> <!-- 事务管理器以及数据源 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>4.3.29.RELEASE</version> </dependency> <!-- mysql驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency>
使用注解
在这里采用的是spring中的数据源
<!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 启用事务注解 --> <tx:annotation-driven transaction-manager="transactionManager"/>
当然由于是使用的注解,不要忘记组件扫描
<context:component-scan base-package="com.zhanghe.study.spring4.beans.tx"/>
之后就可以在要保证事务的方法上配置@Transactional以及在该注解上配置相应的事务隔离级别(isolation)、事务传播行为(propagation)、对哪些异常执行回滚(rollbackFor)以及不执行回滚(noRollbackFor) 默认对运行时异常回滚
使用XML
<!-- 数据源 --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/spring?useUnicode=true&characterEncoding=utf-8" /> <property name="username" value="root" /> <property name="password" value="123456" /> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 使用xml配置事务属性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 根据方法名指定特定的事务属性 --> <tx:method name="get*" read-only="true"/> <tx:method name="find*" read-only="true"/> <tx:method name="save*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 使用事务切入点,把事务切入点和事务属性关联起来 --> <aop:config> <aop:pointcut id="pointCut" expression="execution(* com.zhanghe.study.spring4.beans.tx.UserService.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/> </aop:config>
加载全部内容