SqlSession
是 MyBatis 中与数据库交互的核心接口,它提供了执行 SQL 语句、管理事务、获取 Mapper 接口代理对象等关键功能。 SqlSession
实例 不是直接通过 new
关键字创建的,而是通过 SqlSessionFactory
工厂来创建的。 SqlSessionFactory
负责创建 SqlSession
实例,并管理 SqlSession
的生命周期。
1. SqlSession
的创建方式:通过 SqlSessionFactory
工厂
SqlSession
的创建完全依赖于 SqlSessionFactory
工厂。 SqlSessionFactory
接口提供了多个 openSession()
方法的重载版本,用于创建不同类型的 SqlSession
实例。 最常用的创建 SqlSession
的方式是通过 SqlSessionFactory.openSession()
方法。
常见的 SqlSessionFactory.openSession()
方法调用方式:
-
SqlSession openSession()
(最常用):SqlSessionFactory sqlSessionFactory = ...; // 假设已经创建了 SqlSessionFactory 实例 SqlSession sqlSession = sqlSessionFactory.openSession(); // 创建一个新的 SqlSession 实例
- 这是最常用的方式,创建一个默认配置的
SqlSession
实例。 - 默认情况下,
SqlSession
实例不会自动提交事务 (autoCommit = false)。 需要手动调用sqlSession.commit()
提交事务,或sqlSession.rollback()
回滚事务。 - 默认情况下,
SqlSession
使用ExecutorType.SIMPLE
执行器。
- 这是最常用的方式,创建一个默认配置的
-
SqlSession openSession(boolean autoCommit)
:SqlSession sqlSession = sqlSessionFactory.openSession(true); // 创建一个自动提交事务的 SqlSession 实例
- 创建一个
SqlSession
实例,并 设置事务是否自动提交。 autoCommit = true
:SqlSession
会自动提交事务。 每次执行 SQL 语句后,事务会自动提交。 适用于不需要手动控制事务的简单场景。autoCommit = false
:SqlSession
不会自动提交事务 (默认值)。 需要手动调用sqlSession.commit()
或sqlSession.rollback()
来管理事务。 适用于需要手动控制事务边界的场景。
- 创建一个
-
SqlSession openSession(ExecutorType executorType)
:SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); // 创建一个使用 BATCH 执行器的 SqlSession 实例
- 创建一个
SqlSession
实例,并 指定使用的执行器类型 (ExecutorType)。 ExecutorType
是一个枚举,定义了 MyBatis 执行 SQL 语句的不同执行器类型:ExecutorType.SIMPLE
(默认): 简单执行器。 每次执行 SQL 语句都会创建一个新的Statement
对象。 性能相对较低,但实现简单。ExecutorType.REUSE
: 复用执行器。 复用Statement
对象。 如果执行相同的 SQL 语句 (只是参数不同),可以复用Statement
对象,提高性能。ExecutorType.BATCH
: 批量执行器。 支持批量执行 SQL 语句,可以显著提高批量操作的性能。 适用于批量插入、批量更新等场景。
- 创建一个
-
SqlSession openSession(TransactionIsolationLevel level)
(已过时):// @Deprecated in MyBatis 3.5.x and removed in MyBatis 3.6.x // SqlSession sqlSession = sqlSessionFactory.openSession(TransactionIsolationLevel.READ_COMMITTED);
- 已过时 (Deprecated) 且已移除: 在 MyBatis 3.5.x 中被标记为过时,并在 MyBatis 3.6.x 中被移除。 不再推荐使用此方法,事务隔离级别应该在数据源连接池或事务管理器中配置。
-
SqlSession openSession(ExecutorType executorType, boolean autoCommit)
:SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE, true); // 创建一个使用 REUSE 执行器并自动提交事务的 SqlSession 实例
- 创建一个
SqlSession
实例,同时指定执行器类型和是否自动提交事务。 - 结合了
openSession(ExecutorType executorType)
和openSession(boolean autoCommit)
两个方法的参数。
- 创建一个
-
SqlSession openSession(Connection connection)
:Connection connection = ...; // 假设已经获取了 JDBC Connection 对象 (例如从数据源) SqlSession sqlSession = sqlSessionFactory.openSession(connection); // 使用已有的 Connection 对象创建 SqlSession 实例
- 创建一个
SqlSession
实例,并 使用已有的 JDBCConnection
对象。 - 适用于需要 复用外部事务管理 的场景,例如在 Spring 事务管理下,Spring 会提供
Connection
对象,MyBatis 可以复用 Spring 管理的Connection
和事务。 - 使用此方法创建的
SqlSession
不会从数据源获取新的连接,而是直接使用传入的Connection
对象。SqlSession
也不会负责关闭传入的Connection
对象,连接的关闭责任由外部调用者承担。
- 创建一个
-
SqlSession openSession(ExecutorType executorType, TransactionIsolationLevel level)
(已过时):// @Deprecated in MyBatis 3.5.x and removed in MyBatis 3.6.x // SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, TransactionIsolationLevel.SERIALIZABLE);
- 已过时 (Deprecated) 且已移除: 同样被标记为过时并移除,不推荐使用。
-
SqlSession openSession(ExecutorType executorType, Connection connection)
:Connection connection = ...; SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, connection); // 创建一个使用 BATCH 执行器并使用已有 Connection 的 SqlSession 实例
- 创建一个
SqlSession
实例,同时指定执行器类型和使用已有的 JDBCConnection
对象。 - 结合了
openSession(ExecutorType executorType)
和openSession(Connection connection)
两个方法的参数。
- 创建一个
-
SqlSession openSession(ExecutorType executorType, boolean autoCommit, TransactionIsolationLevel level)
(已过时):// @Deprecated in MyBatis 3.5.x and removed in MyBatis 3.6.x // SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE, true, TransactionIsolationLevel.REPEATABLE_READ);
- 已过时 (Deprecated) 且已移除: 同样被标记为过时并移除,不推荐使用。
2. SqlSession
与 SqlSessionFactory
的关系:工厂和产品
SqlSession
和 SqlSessionFactory
之间是典型的 工厂模式 (Factory Pattern) 的关系:
-
SqlSessionFactory
是工厂 (Factory):SqlSessionFactory
接口及其实现类 (通常是DefaultSqlSessionFactory
) 充当 工厂 的角色。SqlSessionFactory
的职责是创建和管理SqlSession
实例。 它负责创建SqlSession
对象,并为SqlSession
提供必要的配置信息 (例如Configuration
对象)。SqlSessionFactory
是一个 重量级对象,创建过程相对耗时,但在应用的整个生命周期中,通常 只需要创建一个SqlSessionFactory
实例 (单例)。
-
SqlSession
是产品 (Product):SqlSession
接口及其实现类 (通常是DefaultSqlSession
) 充当 产品 的角色。SqlSession
是 MyBatis 与数据库交互的主要接口。 开发者通过SqlSession
执行 SQL 语句、管理事务、获取 Mapper 接口代理对象等。SqlSession
是一个 轻量级对象,创建速度快。 但SqlSession
不是线程安全的。 最佳实践是 在每个线程中获取一个新的SqlSession
实例,并在使用完成后及时关闭 (sqlSession.close()
)。 通常,SqlSession
的生命周期应该 尽可能短 (Request-Scoped)。
关系总结:
SqlSessionFactory
是SqlSession
的工厂,负责创建SqlSession
实例。SqlSessionFactory
是单例的 (Singleton),在应用生命周期内通常只有一个实例。SqlSession
是非线程安全的,轻量级的,通常是请求作用域 (Request-Scoped) 的,每次数据库操作都应该获取新的SqlSession
实例。SqlSessionFactory
内部持有Configuration
对象,SqlSession
从SqlSessionFactory
获取Configuration
信息,并使用Configuration
进行 SQL 执行、结果映射等操作.
简单比喻:
你可以将 SqlSessionFactory
比喻成一个 汽车工厂,而 SqlSession
比喻成 工厂生产的汽车。
- 汽车工厂 (
SqlSessionFactory
): 负责生产汽车 (SqlSession
)。 工厂本身很大,建造工厂成本很高 (创建SqlSessionFactory
耗时),但工厂可以持续生产汽车。 - 汽车 (
SqlSession
): 工厂生产的产品,用于实际的驾驶 (数据库操作)。 汽车相对轻便,容易生产 (创建SqlSession
速度快),但汽车是消耗品,需要定期维护和更换 (SqlSession
不是线程安全的,需要短生命周期)。
3. SqlSession
的生命周期和使用:
- 获取
SqlSession
: 通过SqlSessionFactory.openSession()
方法获取SqlSession
实例。 - 执行数据库操作: 使用
SqlSession
提供的各种方法 (例如selectOne()
,selectList()
,insert()
,update()
,delete()
,getMapper()
等) 执行 SQL 语句或获取 Mapper 接口代理对象。 - 管理事务 (如果
autoCommit = false
):sqlSession.commit()
: 提交事务。sqlSession.rollback()
: 回滚事务。
- 关闭
SqlSession
: 务必在使用完成后及时关闭SqlSession
(sqlSession.close()
).close()
方法会释放SqlSession
占用的资源 (例如 JDBC 连接),并将其归还给连接池 (如果使用了连接池数据源)。 不及时关闭SqlSession
会导致资源泄漏,影响系统性能和稳定性。 通常在finally
块中关闭SqlSession
,确保无论是否发生异常,SqlSession
都能被正确关闭。
代码示例 (完整的 SqlSession
使用流程):
SqlSession sqlSession = null;
try {sqlSession = sqlSessionFactory.openSession(); // 获取 SqlSession 实例UserMapper userMapper = sqlSession.getMapper(UserMapper.class); // 获取 Mapper 接口代理对象User user = userMapper.getUserById(1); // 执行 SQL 操作// ... 其他数据库操作 ...sqlSession.commit(); // 提交事务 (如果 autoCommit = false)return user;} catch (Exception e) {if (sqlSession != null) {sqlSession.rollback(); // 回滚事务 (如果发生异常)}throw e; // 抛出异常
} finally {if (sqlSession != null) {sqlSession.close(); // 关闭 SqlSession, 释放资源}
}
总结:
SqlSession
是 MyBatis 与数据库交互的核心接口,它通过 SqlSessionFactory
工厂创建。 SqlSessionFactory
是重量级对象,负责创建和配置 SqlSession
,而 SqlSession
是轻量级对象,用于执行 SQL 语句和管理事务。 理解 SqlSession
的创建方式和与 SqlSessionFactory
的关系,以及 SqlSession
的生命周期管理,对于正确使用 MyBatis 至关重要。 在 MyBatis 应用中,开发时遵循 “获取 SqlSession
-> 执行数据库操作 -> 管理事务 -> 关闭 SqlSession
” 的标准流程,确保资源正确释放和事务的正确性。