数据库事务(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
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);
}
}
执行结果
控制台报删除语句的错误
数据库执行了添加,没有删除,导致数据不一致问题
声明式事务:AOP 的应用,不影响业务代码。
在 Spring 的配置文件中创建一个 DataSourceTransactionManager
对象
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<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>
控制台报错
数据库数据保持了一致性
编程式事务:在代码中进行事务的管理。