SqlSession

246 阅读3分钟

MyBatis 中的 SqlSession 是执行数据库操作的核心对象,它代表了一次数据库会话。通过 SqlSession,开发者可以执行 SQL 命令、获取 Mapper 接口、管理事务等。


1. SqlSession 的作用

  • 执行 SQL:直接运行 SQL 语句(如 selectinsertupdatedelete)。
  • 获取 Mapper:通过 getMapper() 方法获取 Mapper 接口的代理对象,简化数据库操作。
  • 事务管理:支持手动提交(commit())和回滚(rollback()),或通过配置自动提交。
  • 配置管理:关联 Configuration 对象,访问 MyBatis 全局配置。

2. SqlSession 的生命周期

  • 非线程安全:每个线程应使用独立的 SqlSession 实例,避免多线程冲突。

  • 作用域建议:

    • 方法级别:在方法内部创建,使用后及时关闭(推荐)。
    • 请求级别:在 Web 应用中,每个 HTTP 请求创建一个 SqlSession,请求结束后关闭。
    • 会话级别:长期存在的场景(如桌面应用),需手动管理事务和关闭。

3. 获取 SqlSession

通过 SqlSessionFactory 创建:

SqlSessionFactory sqlSessionFactory = ...; // 通常从配置文件中构建
try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
    // 执行数据库操作
} // 自动关闭,避免资源泄漏

4. 常用方法

4.1 执行 SQL

  • selectOne(String statement, Object parameter) 执行返回单个结果的 SQL,若结果不唯一会抛出异常。
  • selectList(String statement, Object parameter) 执行返回列表的 SQL。
  • selectMap(String statement, Object parameter, String mapKey) 将结果集转换为 Map,指定 Map 的键字段。
  • insert(String statement, Object parameter) 执行插入操作,返回影响行数。
  • update(String statement, Object parameter) 执行更新操作。
  • delete(String statement, Object parameter) 执行删除操作。

4.2 获取 Mapper

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.selectById(1);

4.3 事务控制

  • 手动提交

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

    java复制代码
    ​
    SqlSession sqlSession = sqlSessionFactory.openSession(true); // autoCommit=true
    

5. 最佳实践

  • 资源管理:使用 try-with-resources(Java 7+)自动关闭 SqlSession:

    try (SqlSession sqlSession = sqlSessionFactory.openSession()) {
        // 操作数据库
        sqlSession.commit();
    } // 自动关闭
    
  • 避免长事务:长时间未提交的 SqlSession 会占用数据库连接,需及时提交或回滚。

  • 与 Spring 集成:在 Spring 中,通过 SqlSessionTemplate 自动管理 SqlSession 生命周期,无需手动关闭。


6. 底层原理

  • 动态代理getMapper() 通过 JDK 动态代理生成 Mapper 接口的实现类,将方法调用转换为 SQL 执行。
  • Executor:SqlSession 内部依赖 Executor 对象(如 SimpleExecutorReuseExecutor)执行 SQL。
  • Configuration:SqlSession 持有 Configuration 对象,存储 MyBatis 全局配置(如映射文件、类型处理器)。

7. 常见问题

  • Q:SqlSession 线程安全吗? A:非线程安全,需在多线程环境下为每个线程创建独立实例。
  • Q:未关闭 SqlSession 会导致什么问题? A:数据库连接泄漏,最终可能耗尽连接池资源。
  • Q:如何避免 N+1 查询问题? A:通过懒加载(lazyLoadingEnabled)或联表查询优化,合理使用 selectList 批量查询。

总结

SqlSession 是 MyBatis 与数据库交互的桥梁,合理使用其方法和生命周期管理,能确保数据访问层的高效性和安全性。在集成框架(如 Spring)中,通常无需手动管理 SqlSession,但理解其原理对优化性能和排查问题至关重要。