1. 回顾事务
1. 概念
- 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性
- 换句话说,事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用
- 事务的底层使用的使 AOP
2. 事务四个属性(ACID)
- 原子性(atomicity)
事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用 - 一致性(consistency)
一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中 - 隔离性(isolation)
可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏 - 持久性(durability)
事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中
2. 测试
-
在之前的案例中,我们给userDao接口新增两个方法,删除和增加用户
//添加一个用户 int addUser(User user); //根据id删除用户 int deleteUser(int id);
-
mapper文件,先故意把 deletes 写错
<insert id="addUser" parameterType="com.pojo.User"> insert into user (id,name,pwd) values (#{id},#{name},#{pwd}) </insert> <delete id="deleteUser" parameterType="int"> deletes from user where id = #{id} </delete>
-
编写接口的实现类,在实现类中
public class UserDaoImpl extends SqlSessionDaoSupport implements UserMapper { //增加一些操作 public List<User> selectUser() { User user = new User(4,"小明","123456"); UserMapper mapper = getSqlSession().getMapper(UserMapper.class); mapper.addUser(user); mapper.deleteUser(4); return mapper.selectUser(); } //新增 public int addUser(User user) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.addUser(user); } //删除 public int deleteUser(int id) { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); return mapper.deleteUser(id); } }
-
测试
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); }
报错:sql异常,delete写错了,修改后
结果 :插入成功!
- 没有进行事务的管理;我们想让他们都成功才成功,有一个失败,就都失败,我们就应该需要事务!
3. Spring中的事务管理
1. 使用 XML 配置方式进行事务管理
- Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理
-
编程式事务管理
-
将事务管理代码嵌到业务方法中来控制事务的提交和回滚
-
缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码
-
-
声明式事务管理
-
一般情况下比编程式事务好用。
-
将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
-
将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
-
-
使用Spring管理事务
- 注意头文件的约束导入 : tx
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
-
事务管理器
-
无论使用Spring的哪种事务管理策略(编程式或者声明式)事务管理器都是必须的。
-
就是 Spring的核心事务管理抽象,管理封装了一组独立于技术的方法。
-
-
JDBC事务
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean>
-
配置好事务管理器后我们需要去配置事务的通知
<!--配置事务通知--> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!--配置哪些方法使用什么样的事务,配置事务的传播特性--> <tx:method name="add" propagation="REQUIRED"/> <tx:method name="delete" propagation="REQUIRED"/> <tx:method name="update" propagation="REQUIRED"/> <tx:method name="search*" propagation="REQUIRED"/> <tx:method name="get" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
-
spring事务传播特性:
spring支持7种事务传播行为:- propagation_requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。
- propagation_supports:支持当前事务,如果没有当前事务,就以非事务方法执行。
- propagation_mandatory:使用当前事务,如果没有当前事务,就抛出异常。-
- propagation_required_new:新建事务,如果当前存在事务,把当前事务挂起。
- propagation_not_supported:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- propagation_never:以非事务方式执行操作,如果当前事务存在则抛出异常。
- propagation_nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作
Spring 默认的事务传播行为是 PROPAGATION_REQUIRED,它适合于绝大多数的情况。
-
配置AOP
导入aop的头文件!<!--配置aop织入事务--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.dao.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config>
测试
@Test public void test2(){ ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); UserMapper mapper = (UserMapper) context.getBean("userDao"); List<User> user = mapper.selectUser(); System.out.println(user); }
-
思考 : 为什么需要配置事务?
- 如果不配置,就需要我们手动提交控制事务;
- 事务在项目开发过程非常重要,涉及到数据的一致性的问题
2. 使用注解方式进行管理(常用)
- 引入命名空间
- 在 XML 中船舰事务管理器 并 开启事务
- 在 Service 类中添加注解 ==@Transactional ==
-
@Transactional 可配参数
1. propagation() :事务传播行为 ,多 事务方法 直接进行调用,这个过程中事务是如何进行管理的 事务方法 :使数据表中数据发生变化的操作(增、删、改) 7 中行为: REQUIRED(0) :如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 SUPPORTS(1) :如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行。 MANDATORY(2) :如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。 REQUIRES_NEW(3) :它会开启一个新的事务。如果一个事务已经存在,则先将这个存在的事务挂起。 NOT_SUPPORTED(4) :总是非事务地执行,并挂起任何存在的事务。 NEVER(5) :总是非事务地执行,如果存在一个活动事务,则抛出异常。 NESTED(6) :如果一个活动的事务存在,则运行在一个嵌套的事务中。 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。 2. isolation() :隔离级别 3. timeout() :超时时间(单位 : s) ,设置在多少时间内进行提交,如果设定时间内没提交则回滚,默认 :-1,即没有超时时间 4. readOnly() :是否只读 ,默认值 :false,设置成 True 后,该事务中只能查询 5. rollbackFor() :设置出现哪些异常 进行 事务回滚 6. noRollbackFor() :设置出现哪些异常 不进行 事务回滚