事务:包含一组sql语句的操作,要么都成功要么都失败。
事务的四个原则:ACID
- 原子性:在一个事务当中的所有操作应该被视为一个不可分割的整体,要么全成功,要么全部失败,即A给B转200,A少了200,B就多了200,不能A少了,B没多
- 一致性:倘若事务操作失败,则回滚事务时,与原始状态一致,成功则操作前后数据的完整性保持一致,比如执行前A和B加起来是一千,A给B转完200之后,两者之和还是1000.
- 隔离性:当你在进行事务操作时,其他事务的操作不能影响到你的事务操作,比如A对B操作,另一个事务中C也在对B操作,这时就要满足隔离性,或者A提交完之后C再继续,不然可能会出现一些问题(脏读、不可重复读、幻读)。
- 持久性:事务没有完成,就回滚到初始状态,事务完成了之后,这个事务对数据库所作出的修改就被持久地保存进了数据库当中,不会再被回滚操作影响。即使出现了各种事故,比如机房断电、网络故障等等意外情况,数据库当中的数据也不能丢失。
spring中对于事务的管理可以使用aop完成,我们先来一个实例
我们数据库此时的数据为
对于一个pojo为User的类,其UserMapper为
public interface UserMapper {
List<User> getAllUser();
int addUser(User user);
int delUser(int id);
}
看其UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.li.dao.UserMapper">
<select id="getAllUser" resultType="user">
select * from user;
</select>
<insert id="addUser" parameterType="user">
insert into user(id, name, pwd) VALUES (#{id},#{name},#{pwd});
</insert>
<delete id="delUser" >
deletes from user where id=#{id};
</delete>
</mapper>
可以看出其delete方法又明显的错误,执行一定会报错。
这里我们采用的是第二种生成sqlSession的方法
public class UserMapper2 extends SqlSessionDaoSupport implements UserMapper {
@Override
public List<User> getAllUser() {
addUser(new User(4,"精心会","5555"));
delUser(3);
return getSqlSession().getMapper(UserMapper.class).getAllUser();
}
@Override
public int addUser(User user) {
return getSqlSession().getMapper(UserMapper.class).addUser(user);
}
@Override
public int delUser(int id) {
return getSqlSession().getMapper(UserMapper.class).delUser(id);
}
}
执行
@Test
public void s111s(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserMapper userMapper2 = context.getBean("userMapper2", UserMapper.class);
List<User> allUser = userMapper2.getAllUser();
for (User user : allUser) {
System.out.println(user);
}
}
如所预计的报了错,数据库中第四条记录已经增加上了,这很明显违背了事务的原则,理论上不应该增加上的,接下来我们用spring的事务管理。
先配置声明式事务,随后配置事务通知,再借助aop实现事务的织入
<!--配置声明式事务-->
<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="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="ttAdvice" expression="execution(* com.li.dao.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="ttAdvice"/>
</aop:config>
结果再错误的时候无法实现插入。