# 如何理解SqlSession技术 ## 引言 在现代Java持久层开发中,MyBatis作为一款优秀的ORM框架被广泛应用。而SqlSession作为MyBatis最核心的接口之一,承担着与数据库交互的关键角色。本文将深入剖析SqlSession的技术原理、工作机制以及最佳实践,帮助开发者全面理解这一关键技术。 ## 一、SqlSession概述 ### 1.1 什么是SqlSession SqlSession是MyBatis框架中最重要的接口之一,它代表与数据库的一次会话。通过SqlSession,应用程序可以执行SQL命令、获取映射器(Mapper)和管理事务。 ```java public interface SqlSession extends Closeable { <T> T selectOne(String statement); <E> List<E> selectList(String statement); int insert(String statement); int update(String statement); int delete(String statement); void commit(); void rollback(); <T> T getMapper(Class<T> type); // 其他方法... }
SqlSession的生命周期通常遵循以下原则: - 创建时机:每次需要与数据库交互时创建 - 使用范围:请求或方法级别(非类成员变量) - 销毁时机:使用完毕后立即关闭
SqlSession的典型实现类结构:
SqlSession ├── DefaultSqlSession (默认实现) ├── SqlSessionManager (已废弃) └── SqlSessionTemplate (Spring集成)
sequenceDiagram participant App as 应用程序 participant SqlSession participant Executor participant StatementHandler participant JDBC as JDBC驱动 App->>SqlSession: 执行查询 SqlSession->>Executor: 委派执行 Executor->>StatementHandler: 创建Statement StatementHandler->>JDBC: 执行SQL JDBC-->>StatementHandler: 返回ResultSet StatementHandler-->>Executor: 处理结果 Executor-->>SqlSession: 返回结果 SqlSession-->>App: 返回数据
通过SqlSessionFactory创建SqlSession实例:
String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); try (SqlSession session = sqlSessionFactory.openSession()) { // 业务操作 }
// 查询单个对象 User user = session.selectOne("com.example.mapper.UserMapper.selectById", 1); // 查询列表 List<User> users = session.selectList("com.example.mapper.UserMapper.selectAll"); // 插入数据 int count = session.insert("com.example.mapper.UserMapper.insert", newUser);
// 分页查询 RowBounds rowBounds = new RowBounds(offset, limit); List<User> users = session.selectList( "com.example.mapper.UserMapper.selectByPage", params, rowBounds);
try { session = sqlSessionFactory.openSession(); // 业务操作1 userMapper.update(user1); // 业务操作2 accountMapper.deduct(account); session.commit(); // 提交事务 } catch (Exception e) { session.rollback(); // 回滚事务 } finally { session.close(); }
<mapper namespace="com.example.mapper.UserMapper"> <cache eviction="LRU" flushInterval="60000" size="512"/> </mapper>
// 正确示例(方法局部变量) public User findById(long id) { try (SqlSession session = sqlSessionFactory.openSession()) { return session.selectOne(“findById”, id); } }
2. **结合连接池使用** ```xml <!-- 配置Druid连接池 --> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments>
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) { UserMapper mapper = session.getMapper(UserMapper.class); for (int i = 0; i < 1000; i++) { mapper.insert(new User("user" + i)); if (i % 200 == 0) { session.flushStatements(); // 分批提交 } } session.commit(); }
Map<String, Object> params = new HashMap<>(); params.put("userId", 123); session.selectOne("callUserProcedure", params);
public class AddressTypeHandler extends BaseTypeHandler<Address> { @Override public void setNonNullParameter(PreparedStatement ps, int i, Address parameter, JdbcType jdbcType) { ps.setString(i, parameter.toJson()); } // 其他方法实现... }
Spring通过模板模式封装SqlSession:
public class SqlSessionTemplate implements SqlSession { private final SqlSessionFactory sqlSessionFactory; private final ExecutorType executorType; private final SqlSessionInterceptor interceptor; // 代理模式实现方法调用 private class SqlSessionInterceptor implements InvocationHandler { public Object invoke(Object proxy, Method method, Object[] args) { SqlSession sqlSession = getSqlSession(); try { return method.invoke(sqlSession, args); } finally { closeSqlSession(sqlSession); } } } }
@Configuration @EnableTransactionManagement public class MyBatisConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } }
类型 | 特点 | 适用场景 |
---|---|---|
SIMPLE | 默认执行器 | 常规操作 |
REUSE | 重用预处理语句 | 相同SQL频繁执行 |
BATCH | 批量操作 | 大批量插入/更新 |
开启慢SQL日志
<settings> <setting name="logImpl" value="SLF4J"/> <setting name="defaultStatementTimeout" value="3"/> </settings>
使用P6Spy监控SQL
# application.properties spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/test
连接泄漏
Too many connections
缓存不一致
SqlSession作为MyBatis的核心接口,其正确理解和使用对系统性能和稳定性至关重要。通过本文的系统讲解,希望读者能够掌握SqlSession的底层原理和高级用法,在实际开发中构建更健壮的持久层解决方案。
参考文献: 1. MyBatis官方文档 3.5.x 2. 《MyBatis技术内幕》徐郡明 著 3. Spring Framework 5.x文档 4. Java Persistence with MyBatis(Manning) “`
注:本文实际约5500字,完整5900字版本需要进一步扩展每个章节的案例分析和技术细节。如需完整版,建议补充: 1. 更多性能对比测试数据 2. 分布式环境下的SqlSession管理 3. 与JPA/Hibernate的对比分析 4. 具体项目实战案例
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。