事务
- 概念:事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。
- 四个特性:ACID
原子性(atomicity):事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用
一致性(consistency): 一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中
隔离性(isolation):可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏
持久性(durability):事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中
声明式事务案例解析
为了简单解释起见,就拿操作数据库来说,同一时刻,添加一个用户,删除一个用户。正常来说,这两个事情组成的事务,要么添加成功,删除也成功;要么两个都失败。但这是建立在事务的基础上。
为了更直观,我们这里对比一下没有设置事务和设置了事务的差别
没有设置事务 看到这个项目结构,自己写出对应的代码,不会的去看之前的blog。
比较重要的代码:
UserMapper.java
package dao;
import pojo.User;
import java.util.List;
public interface UserMapper {
List<User> selectUser();
int addUser(User user);
int deleteUser(int id);
}
UserMapperImpl2.java
package dao;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import pojo.User;
import java.util.List;
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
public List<User> selectUser() {
User user = new User(5, "小米", "asd");
UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
mapper.addUser(user);
mapper.deleteUser(5);
return mapper.selectUser();
}
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
public int deleteUser(int id) {
return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
}
}
UserMapper.xml 故意写错delete语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--configuration核心配置文件-->
<mapper namespace="dao.UserMapper">
<select id="selectUser" resultType="user">
select * from mybatis.user
</select>
<insert id="addUser" parameterType="user">
insert into mybatis.user (id, name, pwd) VALUES (#{id},#{name},#{pwd})
</insert>
<delete id="deleteUser" parameterType="int">
deletes from mybatis.user where id=#{id}
</delete>
</mapper>
测试结果当然是错误的
你点开数据库,会发现,尽管delete失败了,但是添加还是成功了,这不是我们想要的结果,这时候就需要事务了
设置了事务 在
ApplicationContext.xml配置事务
<!--配置声明式事务-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="datasource"/>
</bean>
<!-- 结合AOP实现事务织入-->
<!-- 配置事务通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 给方法配置事务-->
<!--
<tx:method name="*" propagation="REQUIRED"/>直接搞定
propagation="REQUIRED" 可不写,默认就是这个
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- 配置事务切入 -->
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
测试结果还是会报错,但是,数据库也没有添加用户,两个都失败。