Mybatis事务
1.为什么需要事务
在现代软件开发中,尤其是涉及到数据库操作的场景,事务是不可或缺的一部分。事务的存在主要是为了解决数据一致性和操作原子性的问题。在一个复杂的业务流程中,可能涉及到多个数据库操作,例如在一个电商系统中,一个订单的生成可能包括以下步骤:
-
在订单表中插入一条记录。
-
更新商品表中的库存数量。
-
更新用户表中的余额或积分等。
如果这些操作不能作为一个整体来执行,可能会导致数据的不一致。例如,订单记录插入成功,但库存更新失败,这将导致系统中的数据出现错误。事务的作用就是确保这些操作要么全部成功,要么全部失败,从而保证数据的完整性和一致性。

2.事务是什么?
- 事务本身是一个完整的业务流程,是不可再分的工作单元。
- 事务只和DML(增删改)语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。
- 多个操作同时进行,那么同时成功,那么同时失败。这就是事务。
3.事务的四大特征
事务有四个特性:
- 原子性:指一个事务是一个不可分割的工作单位,其中的操作要么都成功,要么都失败。
- 持久性:指事务一旦提交,他对数据库的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。(执行后,停电后不可回复之前的状态)
- 隔离性:事务内部的操作与其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 一致性:事务执行的结果必须是使数据库从一个一致状态变到另一个一致状态。(转账前后钱总和不变)
比如有一个订单业务
1.订单表当中添加一条记录
2.商品数量数据更新(减少)
3.....
当多个任务同时进行操作的时候,这些任务只能同时成功,或者同时失败。
4.mysql如何去使用事务
实现张三给李四转账100元
- 没有添加事务(完成转账)
update act set money = 300 where id = 1; update act set money = 100 where id = 2;
以上的写法并没有添加事务,那么一旦在sql执行过程中出现了问题,就会出现意外。
- 添加事务:
start transaction; //开启事务
update act set money = 300 where id = 1;
update act set money = 100 where id = 2;
commit; //提交事务
rollback; //事务的回滚
事务的优点在于,sql在执行的过程中一旦出现问题,那么可以回滚到原来的状态。不写 rollback; 事务不会回滚。

5.Mybatis关于事务的管理
MyBatis框架中的事务默认是手动提交的,也就是每次编写程序都需要调用commit()方法提交事务
<transactionManager type="JDBC"></transactionManager> ====》程序员自己控制处理的提交和回滚

设置自动提交事务,可以通过openSession的方法进行设置,openSession(true) 自动提交事务。代码如下:(配置中的策略不变)
public class UserTest {
private InputStream in = null;
private SqlSession session = null;
private UserDao mapper = null;
@Before //前置通知, 在方法执行之前执行
public void init() throws IOException {
//加载主配置文件,目的是为了构建SqlSessionFactory对象
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory对象
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
//通过SqlSessionFactory工厂对象创建SqlSesssion对象
session = factory.openSession(true); //关闭
//通过Session创建UserDao接口代理对象
mapper = session.getMapper(UserDao.class);
}
@After //@After: 后置通知, 在方法执行之后执行 。
public void destory() throws IOException {
//释放资源
session.close();
in.close();
}
@Test
public void insertMoreByList(){
User user1 = new User("a1","男","北京");
User user2 = new User("a2","男","北京");
User user3 = new User("a3","男","北京");
List<User> users = Arrays.asList(user1,user2,user3);
int result = mapper.insertMoreByList(users);
//session.commit(); //手动提交事务
System.out.println(result);
}
}

6.实践案例:使用MyBatis实现批量插入
以下是一个使用MyBatis实现批量插入的实践案例。在这个案例中,我们将使用自动提交事务的方式。
1. 配置文件
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"></transactionManager>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/test"/>
<property name="username" value="root"/>
<property name="password" value="password"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="UserMapper.xml"/>
</mappers>
</configuration>
2. Mapper接口
public interface UserDao {
int insertMoreByList(List<User> users);
}
3. Mapper XML文件
<mapper namespace="com.example.UserDao">
<insert id="insertMoreByList" parameterType="list">
INSERT INTO user (name, gender, address) VALUES
<foreach collection="list" item="user" index="index" separator=",">
(#{user.name}, #{user.gender}, #{user.address})
</foreach>
</insert>
</mapper>
4. 测试代码
public class UserTest {
private InputStream in = null;
private SqlSession session = null;
private UserDao mapper = null;
@Before
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession(true); // 自动提交事务
mapper = session.getMapper(UserDao.class);
}
@After
public void destory() throws IOException {
session.close();
in.close();
}
@Test
public void insertMoreByList() {
User user1 = new User("a1", "男", "北京");
User user2 = new User("a2", "男", "北京");
User user3 = new User("a3", "男", "北京");
List<User> users = Arrays.asList(user1, user2, user3);
int result = mapper.insertMoreByList(users);
System.out.println(result);
}
}
在这个案例中,我们使用了自动提交事务的方式,通过openSession(true)
方法开启了一个自动提交的SqlSession
。在执行批量插入操作时,MyBatis会自动提交事务,简化了代码的复杂性。
7、总结
事务是数据库操作中一个非常重要的概念,它确保了数据的一致性和操作的原子性。通过事务的四大特性(ACID),可以有效地解决并发操作和数据一致性问题。在MySQL中,事务的使用通过START TRANSACTION
、COMMIT
和ROLLBACK
等命令来实现。在MyBatis中,事务的管理可以通过配置文件和代码来实现,支持手动提交和自动提交两种方式。通过合理使用事务,可以提高系统的可靠性和稳定性,确保数据的正确性。