深入聊聊 MyBatis 中的 sqlSession 生命周期

发布时间:2023-05-20

MyBatis 中 sqlSession 的生命周期

MyBatis 是一款优秀的 ORM 工具,与 Hibernate 相比,它的学习曲线和上手难度相对较低,同时它也支持丰富的配置和插件扩展。在 MyBatis 中,sqlSession 是我们常用的一个核心接口,今天我们就从多个方面来详细阐述 sqlSession 的生命周期。

一、sqlSession 生命周期面试

在阐述 sqlSession 生命周期的时候,我们可以从面试官经常问到的问题来展开思路。下面,我们列举了一些经典的问题和答案,帮助大家更好地了解 sqlSession 生命周期。

二、sqlSession 生命周期 ThreadLocal

在多线程环境下,我们需要保证同一个线程内使用的 sqlSession 是同一个实例,否则线程不安全。为了解决这个问题,MyBatis 使用了 ThreadLocal 技术。ThreadLocal 是 JDK 提供的一个线程封闭的变量,每个线程都有自己的一个变量,互不干扰。MyBatis 在每次创建 sqlSession 的时候,会将 sqlSession 放入当前线程的 ThreadLocal 变量中,这样,在当前线程中调用 sqlSession 时,会使用同一个 sqlSession 实例。 下面是一个基于 ThreadLocal 的 sqlSession 生命周期代码示例:

// 定义一个 ThreadLocal 变量,存储 sqlSession
private static final ThreadLocal<SqlSession> sqlSessionThreadLocal = new ThreadLocal<>();
public SqlSession getSqlSession() {
    // 获取当前线程绑定的 sqlSession 变量
    SqlSession sqlSession = sqlSessionThreadLocal.get();
    // 如果变量为空,说明当前线程中没有 sqlSession 对象,需要创建一个新的 sqlSession 对象并绑定到当前线程
    if (sqlSession == null) {
        sqlSession = sqlSessionFactory.openSession();
        sqlSessionThreadLocal.set(sqlSession);
    }
    return sqlSession;
}
public void closeSqlSession() {
    // 获取当前线程绑定的 sqlSession 变量
    SqlSession sqlSession = sqlSessionThreadLocal.get();
    // 如果变量不为空,说明当前线程有 sqlSession 对象,需要将其关闭
    if (sqlSession != null) {
        sqlSession.close();
        sqlSessionThreadLocal.remove();
    }
}

三、sqlSession 生命周期流程

MyBatis 的 sqlSession 生命周期总体可以划分为四个阶段:创建、使用、提交或回滚、关闭。下面我们就详细介绍一下这四个阶段的流程和相关的 API。

1. 创建 sqlSession

创建 sqlSession 是最简单的一步,只需要通过 SqlSessionFactory 获取 sqlSession 实例即可。具体代码如下:

// 通过 SqlSessionFactory 获取 sqlSession 实例
SqlSession sqlSession = sqlSessionFactory.openSession();

2. 使用 sqlSession

使用 sqlSession 是最常见的操作,主要包括查询、更新、删除等操作。MyBatis 给 sqlSession 提供了丰富的 API,包括 selectOneselectListinsertupdatedelete 等方法,具体使用方法如下:

// 查询单个对象
Object result = sqlSession.selectOne("namespace.id", parameter);
// 查询列表对象
List<Object> result = sqlSession.selectList("namespace.id", parameter);
// 插入对象
int result = sqlSession.insert("namespace.id", parameter);
// 更新对象
int result = sqlSession.update("namespace.id", parameter);
// 删除对象
int result = sqlSession.delete("namespace.id", parameter);

3. 提交或回滚

当我们对数据库进行了修改时,需要提交修改或回滚操作,避免脏数据的产生。MyBatis 中用 sqlSession 提供了 commitrollback 方法来完成这个操作。

// 提交事务
sqlSession.commit();
// 回滚事务
sqlSession.rollback();

4. 关闭 sqlSession

使用完 sqlSession 后,需要将其关闭,释放资源。MyBatis 调用 sqlSession.close() 方法即可关闭 sqlSession

// 关闭 sqlSession
sqlSession.close();

四、总结

本文从面试、ThreadLocal、流程三个方面详细阐述了 MyBatis 的 sqlSession 生命周期,希望读者能够更全面地了解 sqlSession 的使用方法,减少错误的使用方式和产生的不良后果。