实际开发没接触过SqlSession?真相是它被框架“藏”起来了

3 阅读7分钟

很多后端开发者在使用MyBatis开发时,都会有一个疑问:明明MyBatis的核心是SqlSession,是与数据库交互的直接入口,但自己日常开发中,却从来没有手动写过SqlSession相关的代码,甚至很少听到这个概念。其实并非你没用到SqlSession,而是它被Spring、Spring Boot等主流框架隐性封装,再加上项目分层架构和开发规范的约束,让你无需直接操作,就能间接使用它的核心功能。本文将结合实际开发场景,拆解SqlSession被“隐藏”的原因,搭配独立构思的代码示例,帮你理清SqlSession与日常开发的关联,明白“没接触”不代表“没使用”。

一、一句话理清核心:你一直在间接使用SqlSession

SqlSession是MyBatis中封装JDBC连接、执行SQL、管理事务和缓存的核心接口,是MyBatis操作数据库的“桥梁”。实际开发中,你调用的每一个Mapper接口方法(如selectUserByUsername),底层都由框架通过SqlSession完成执行,只是框架帮你处理了SqlSession的创建、管理和关闭,你无需手动干预,自然不会直接接触到它。

二、核心原因一:Spring Boot自动封装,帮你搞定SqlSession所有操作

日常开发中,我们几乎都会使用Spring Boot整合MyBatis,而Spring Boot提供的MyBatis集成模块,会自动完成SqlSession的全生命周期管理,从创建到关闭,全程无需你写一行代码。

底层封装逻辑(贴合开发实际)

Spring Boot通过SqlSessionTemplate(Spring为MyBatis定制的集成类),将SqlSession实例绑定到当前线程,自动完成以下操作,彻底屏蔽底层细节:

  1. 自动加载MyBatis全局配置文件(mybatis-config.xml)和Mapper映射文件,创建SqlSessionFactory(SqlSession的创建入口);

  2. 每次执行数据库操作时,自动通过SqlSessionFactory创建SqlSession实例;

  3. 执行完SQL后,自动提交/回滚事务,关闭SqlSession,释放数据库连接,避免连接泄露;

  4. 你注入的Mapper接口,底层正是由SqlSessionTemplate通过SqlSession获取的,调用Mapper方法本质就是调用SqlSession的相关方法。

代码示例(你日常写的代码 vs 框架底层代码)

这是你日常开发中写的代码(无任何SqlSession相关内容):

// 1. Mapper接口(你日常编写的内容)
public interface UserMapper {
    User selectUserById(@Param("userId") Integer userId);
}

// 2. Service层(你日常编写的内容,注入Mapper直接调用)
@Service
public class UserService {
    // 注入Mapper,无需关注SqlSession
    @Autowired
    private UserMapper userMapper;
    
    public User getUserById(Integer userId) {
        // 直接调用Mapper方法,底层由SqlSession执行
        return userMapper.selectUserById(userId);
    }
}

// 3. Controller层(你日常编写的内容)
@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    
    @GetMapping("/{userId}")
    public ResponseEntity<User> getUser(@PathVariable Integer userId) {
        User user = userService.getUserById(userId);
        return ResponseEntity.ok(user);
    }
}

这是框架底层帮你自动执行的SqlSession相关代码(你无需编写):

// 框架自动执行,无需你手动编写
public class MyBatisAutoConfiguration {
    // 自动创建SqlSessionFactory
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        // 自动加载Mapper映射文件
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/*.xml"));
        return sessionFactory.getObject();
    }
    
    // 自动创建SqlSessionTemplate,管理SqlSession
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

可以看到,你只需专注于业务逻辑和Mapper接口编写,框架已经帮你把SqlSession的所有底层操作全部处理完毕,你自然不会接触到SqlSession相关代码。

二、核心原因二:项目分层开发,你聚焦业务层,不涉及底层细节

正规项目都会严格遵循“Controller→Service→Mapper”的分层架构,你的日常工作主要集中在Controller层(接收请求)和Service层(实现业务逻辑),而SqlSession属于MyBatis持久层的底层操作,由框架或资深开发者封装处理,你无需关注。

分层开发中的职责划分(清晰易懂)

  • Controller层:接收前端请求,调用Service层方法,返回响应结果,不涉及任何数据库操作;

  • Service层:处理业务逻辑,调用Mapper接口方法,无需关心Mapper底层如何与数据库交互;

  • Mapper层:定义SQL映射(XML或注解),是你唯一接触的持久层代码,底层的SqlSession调用被框架屏蔽;

  • 框架层:负责SqlSession的创建、事务管理、连接释放等底层操作,完全与业务开发分离。

举个例子:你在Service层调用userMapper.selectUserById(userId),只需要知道这个方法能查询到用户数据即可,无需关心底层是如何通过SqlSession获取连接、执行SQL、返回结果的——这些“脏活累活”,都由框架帮你完成。

三、核心原因三:开发规范和工具,进一步规避直接操作SqlSession

实际开发中,统一的开发规范和工具,会进一步减少你接触SqlSession的可能,甚至禁止直接操作SqlSession,避免因手动管理不当导致的问题。

1. 开发规范限制:禁止直接操作SqlSession

正规项目的开发规范中,会明确规定:禁止手动创建、关闭SqlSession,统一通过Mapper接口操作数据库。这是因为手动操作SqlSession容易出现以下问题:

  • 忘记关闭SqlSession,导致数据库连接泄露,耗尽数据库连接池资源;

  • 手动提交/回滚事务不及时,导致数据不一致;

  • 重复创建SqlSession,降低系统性能。

因此,规范会强制要求开发者通过Mapper接口操作数据库,彻底规避直接操作SqlSession的需求。

2. 代码生成工具:自动生成相关代码,无需手动编写

日常开发中,我们会使用MyBatis Generator、MyBatis-Plus Generator等工具,自动生成Mapper接口、XML映射文件,甚至Service层代码。这些工具生成的代码,已经完全遵循“通过Mapper操作数据库”的规范,不会包含任何SqlSession相关的代码,你只需在此基础上修改业务逻辑即可。

// 工具自动生成的Mapper接口(无任何SqlSession相关代码)
public interface UserMapper {
    int deleteByPrimaryKey(Integer userId);
    int insert(User record);
    User selectByPrimaryKey(Integer userId);
    List<User> selectAll();
    int updateByPrimaryKey(User record);
}

四、关键澄清:你混淆了“使用SqlSession”和“直接操作SqlSession”

很多开发者觉得“没接触过SqlSession”,其实是混淆了两个概念:直接操作SqlSession(手动写代码)和间接使用SqlSession(框架帮你操作)。

你每天都在间接使用SqlSession,只是没有直接写相关代码:

  1. 你调用userMapper.selectUserById(),底层是SqlSession通过getMapper()方法获取Mapper实例,再执行SQL;

  2. 你执行增删改操作后,框架自动调用SqlSession的commit()方法提交事务;

  3. 你查询数据时,同一请求中的重复查询会命中SqlSession的一级缓存,这也是SqlSession的核心功能之一。

简单示例:手动操作SqlSession(对比你日常开发)

这是手动操作SqlSession的代码(你日常不会写,框架帮你做了):

// 手动创建SqlSession(日常开发无需编写)
public User manualGetUser(Integer userId) throws IOException {
    // 1. 加载配置文件,创建SqlSessionFactory
    InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    
    // 2. 创建SqlSession实例
    SqlSession sqlSession = sqlSessionFactory.openSession();
    
    try {
        // 3. 获取Mapper实例,执行SQL
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        return userMapper.selectUserById(userId);
    } catch (Exception e) {
        // 4. 异常回滚事务
        sqlSession.rollback();
        throw e;
    } finally {
        // 5. 关闭SqlSession,释放资源
        sqlSession.close();
    }
}

对比你日常写的代码,不难发现:两者的核心逻辑一致,都是通过Mapper执行SQL,但框架帮你省略了所有SqlSession相关的手动操作,让你可以专注于业务本身。

五、总结:SqlSession被“隐藏”,是框架的核心优势

实际开发中没接触过SqlSession,不是因为它不重要,恰恰是因为它太重要,框架才将其封装起来,帮你规避手动操作的风险,降低开发成本。

核心总结:

  1. 框架封装(Spring Boot):自动管理SqlSession的创建、事务、关闭,无需手动编写代码;

  2. 分层开发:你聚焦业务层,底层的SqlSession操作被框架屏蔽;

  3. 开发规范+工具:禁止直接操作SqlSession,自动生成规范代码,进一步减少接触机会;

  4. 你一直在间接使用SqlSession,调用Mapper接口的每一个方法,底层都是SqlSession在工作。

理解SqlSession的作用和被封装的逻辑,不仅能帮你应对MyBatis相关面试,更能让你明白MyBatis与Spring Boot整合的底层原理,在遇到数据库连接、事务相关问题时,能快速定位根源,提升问题排查效率。