事务是什么
例如银行转账时,我们首先要对一个账户进行减法操作,然后再对另一个账户进行加法操作,如果在进行加法操作的时候,发现这个人的账户被冻结了无法进行转入操作,那么这个时候就需要对转出账户进行事务回滚,让钱变为原来的金额,否则就会发生事故,转出账户钱少了,转入账户钱没有多,那你的客户肯定就要找你麻烦了。也就是说:两个或多个sql语句同时执行成功才对数据库进行操作,否则就不操作数据库。
当然这只是举例子,生活中的银行转账肯定远远比这复杂得多。从上图就可以看出,如果说没有事务操作,那么我们的代码就会又需要一个模块来用于处理转账失败之后的操作,费时费力不讨好,这也就体现了事务的重要性。
JDBC中操作事务
在一般的事务管理中,我们需要进行四步操作:
1、设置事务为自动不提交(try)
2、提交事务(try)
3、回滚事务(catch)
4、还原事务为自动提交(fianlly)
下面我们用JDBC开发来看看mybatis的事务如何管理
package com.itclass;
import com.itheima.domain.User;
import org.junit.Test;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class TestJDBC {
@Test
public void test(){
List<User> userList = new ArrayList<>();
//1. 注册驱动
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String url = "jdbc:mysql://localhost:3306/mybatisdb";
String username = "root";
String password = "123456";
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try {
//2. 获取连接
conn = DriverManager.getConnection(url, username ,password);
//事务1 :设置事务手动提交(不能自动提交)
conn.setAutoCommit(false);
// 3. SQL语句
String sql1 = "insert into ......";
String sql2 = "insert into ......";
//4. 创建statement对象: Statement , PreparedStatement
pst = conn.prepareStatement(sql1);
//5. 执行SQL语句,返回结果集
pst.executeUpdate();
pst = conn.prepareStatement(sql2);
pst.executeUpdate();
//事务2:提交事务
conn.commit();
} catch (SQLException e) {
//事务3:出现异常,回顾
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
} finally {
//事务4: 还原状态,设置事务为自动提交
if(conn != null){
try {
conn.setAutoCommit(true);
} catch (SQLException e) {
e.printStackTrace();
}
}
//7. 释放资源: 先开后关
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(pst != null){
try {
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
//打印结果
for (User user : userList) {
System.out.println(user);
}
}
}
从上述代码中可以看出,两个sql语句执行,如果其中一个出了错,会进入到catch语句块当中,执行conn.rollback();事务回滚操作,那么之前的操作全都不算数,数据库并不会更新。
如果成功执行,会执行conn.commit();提交事务,数据库才会更新数据。
无论是否成功执行,都会执行finally语句块当中的conn.setAutoCommit(true);来重置事务操作,以方便别人使用,否则出错之后有可能让别人访问的时候怎么都提交不上去。
Mybatis中如何设置事务
在Mybatis中,事务默认为自动不提交,也就是说在进行增删改操作之后,必须手动提交才能保证数据的保存,否则会进行回滚。由sqlSession来操作事务。
SqlSession sqlSession = sqlSessionFactory.openSession(true); -- 可以自动提交事务的SqlSession对象
SqlSession sqlSession = sqlSessionFactory.openSession(); -- 不可以自动提交事务的SqlSession对象
在创建sqlSession的时候,给openSession中一个true的布尔类型,就可以将事务改为自动提交。