1. 事务
1.1 事务的 ACID 原则
-
数据库事务(transaction)是访问并可能操作各种数据项的一个数据库操作序列。事务必须满足 ACID 原则——即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。
- 原子性指事务是数据库工作的最小单位,一个事务中的所有操作要么全部成功提交,要么全部失败回滚。
- 一致性指事务操作不能破坏数据的一致性,数据库在一个事务的执行前后都应处于一致性状态。
- 隔离性指数据库并发情况下,并发的事务直接是隔离的,一个事务的执行不能被其他事务影响。
- 持久性指一旦事务提交,则其对数据的变更就是永久性的,即使数据库发生任何故障都不应该对数据造成任何影响。
-
以下业务中,虽然执行了添加和删除用户的两个操作,但因为删除操作的失败,导致数据库中的数据与我们原本期望的不一致,因此违反了 ACID 原则,Spring 中有对事务的相关配置来避免此种情况的发生。
-
业务代码
-
User.java
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pw; }
-
UserMapper.java
public interface UserMapper { public List<User> selectUser(); public int addUser(User user); public int deleteUser(int id); }
-
UserMapper.xml
<?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"> <mapper namespace="com.why.mapper.UserMapper"> <insert id="addUser" parameterType="com.why.pojo.User"> insert into user (id, name, pw) values (#{id}, #{name}, #{pw}); </insert> <!--这里将删除语句故意写错--> <delete id="deleteUser" parameterType="int"> deletes from user where id = #{id}; </delete> </mapper>
-
UserMapperImpl.java
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper { public List<User> selectUser() { UserMapper mapper = getSqlSession().getMapper(UserMapper.class); User user = new User(5, "李四", "555555"); mapper.addUser(user); mapper.deleteUser(5); List<User> users = mapper.selectUser(); return users; } public int addUser(User user) { int i = getSqlSession().getMapper(UserMapper.class).addUser(user); return i; } public int deleteUser(int id) { int i = getSqlSession().getMapper(UserMapper.class).deleteUser(5); return i; } }
-
MyTest.xml
@Test public void testProblem() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserMapper userMapper = context.getBean("userMapper", UserMapper.class); List<User> users = userMapper.selectUser(); for (User user : users) { System.out.println(user); } }
-
-
执行结果
-
控制台报删除语句的错误
-
数据库执行了添加,没有删除,导致数据不一致问题
-
-
13.1 Spring 事务管理
-
声明式事务:AOP 的应用,不影响业务代码。
-
在 Spring 的配置文件中创建一个
DataSourceTransactionManager
对象<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!--<constructor-arg ref="dataSource" />--> <property name="dataSource" ref="dataSource"/> </bean>
-
结合 AOP 实现事务的织入
<!--配置事务的类--> <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="query" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!--配置事务切入--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.why.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config>
-
控制台报错
-
数据库数据保持了一致性
-
-
编程式事务:在代码中进行事务的管理。