首页 / 娱乐 / 综艺 / 正文

sqlparameter(MyBatis SQL执行模块详解)

放大字体  缩小字体 来源:体操运动员身高 2026-04-17 17:24  浏览次数:6

本文深入剖析MyBatis的SQL执行模块,带你全面理解Executor执行器体系、缓存机制、事务管理和批处理原理。


一、MyBatis整体架构与SQL执行模块

在深入SQL执行模块之前,我们先了解MyBatis的整体架构,以及SQL执行模块在其中的核心地位。

MyBatis SQL执行模块详解nerror="javascript:errorimg.call(this);">

MyBatis整体架构

1.1 SQL执行模块的核心职责

SQL执行模块主要承担以下核心职责:

1、SQL执行:根据MappedStatement执行SQL语句,并返回结果2、缓存管理:管理一级缓存和二级缓存,提高查询性能3、事务管理:控制数据库事务的提交、回滚和关闭4、批处理支持:支持批量操作,提升数据修改效率5、Statement管理:管理JDBC Statement对象的生命周期6、插件拦截:提供拦截点,支持插件扩展

1.2 Executor接口体系

Executor是SQL执行模块的顶层接口,定义了SQL执行的基本方法:

public interface Executor {    // 执行查询(带缓存Key)    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, CacheKey cacheKey, BoundSql boundSql);    // 执行查询    <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler);    // 执行更新(插入、更新、删除)    int update(MappedStatement ms, Object parameter);    // 刷新批量操作    List<BatchResult> flushStatements();    // 提交事务    void commit(boolean required);    // 回滚事务    void rollback(boolean required);    // 创建CacheKey    CacheKey createCacheKey(MappedStatement ms, Object parameter, RowBounds rowBounds, BoundSql boundSql);    // 判断是否缓存    boolean isCached(MappedStatement ms, CacheKey cacheKey);    // 清空本地缓存    void clearLocalCache();    // 获取事务    Transaction getTransaction();    // 关闭执行器    void close(boolean forceRollback);}

二、Executor执行器架构

MyBatis提供了多种Executor实现,以适应不同的使用场景。

MyBatis SQL执行模块详解nerror="javascript:errorimg.call(this);">

Executor执行器架构

2.1 Executor继承体系

Executor采用了装饰器模式,提供了灵活的功能扩展:

Executor (接口)├── baseExecutor (抽象基类)│   ├── SimpleExecutor (简单执行器)│   ├── ReuseExecutor (可重用执行器)│   └── BatchExecutor (批处理执行器)└── CachingExecutor (缓存执行器)

2.2 baseExecutor抽象基类

baseExecutor实现了Executor接口的大部分功能,定义了SQL执行的基本流程:

public abstract class baseExecutor implements Executor {    protected Transaction transaction;    protected Executor wrapper;    protected ConcurrentlinkedQueue<DeferredLoad<?>> deferredLoads;    protected PerpetualCache localCache;        // 一级缓存    protected PerpetualCache localOutputParameterCache;    protected Configuration configuration;    @Override    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {        // 1. 创建BoundSql        BoundSql boundSql = ms.getBoundSql(parameter);        // 2. 创建CacheKey        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);        // 3. 执行查询        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);    }    @Override    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,                             ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {        // 检查本地缓存        List<E> list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;        if (list != null) {            return list;        }        // 执行数据库查询        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);        return list;    }}

2.3 SimpleExecutor简单执行器

SimpleExecutor是最基础的执行器实现,每次执行SQL都会创建新的Statement对象:

public class SimpleExecutor extends baseExecutor {    @Override    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds,                              ResultHandler resultHandler, BoundSql boundSql) throws SQLException {        Statement stmt = null;        try {            // 1. 创建Configuration对象            Configuration configuration = ms.getConfiguration();            // 2. 创建StatementHandler            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter,                                                                        rowBounds, resultHandler, boundSql);            // 3. 创建Statement            stmt = prepareStatement(handler, ms.getStatementLog());            // 4. 执行查询            return handler.<E>query(stmt, resultHandler);        } finally {            // 5. 关闭Statement            closeStatement(stmt);        }    }    @Override    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {        Statement stmt = null;        try {            Configuration configuration = ms.getConfiguration();            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter,                                                                        RowBounds.DEFAULT, null, null);            stmt = prepareStatement(handler, ms.getStatementLog());            return handler.update(stmt);        } finally {            closeStatement(stmt);        }    }}

2.4 ReuseExecutor可重用执行器

ReuseExecutor会缓存Statement对象,相同SQL可以重用Statement,减少Statement创建开销:

public class ReuseExecutor extends baseExecutor {    private final Map<String, Statement> statementMap = new HashMap<>();    @Override    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds,                              ResultHandler resultHandler, BoundSql boundSql) throws SQLException {        Configuration configuration = ms.getConfiguration();        StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter,                                                                    rowBounds, resultHandler, boundSql);        Statement stmt = prepareStatement(handler, ms.getStatementLog(), boundSql.getSql());        return handler.<E>query(stmt, resultHandler);    }    private Statement prepareStatement(StatementHandler handler, Log statementLog, String sql) throws SQLException {        Statement stmt;        // 尝试从缓存中获取Statement        stmt = statementMap.get(sql);        if (stmt == null) {            // 缓存未命中,创建新的Statement            stmt = prepareStatement(handler, statementLog);            statementMap.put(sql, stmt);        }        return stmt;    }}

2.5 BatchExecutor批处理执行器

BatchExecutor专门用于批量操作,会将多个SQL语句批量执行:

public class BatchExecutor extends baseExecutor {    private final List<Statement> statementList = new ArrayList<>();    private final List<BatchResult> batchResultList = new ArrayList<>();    private String currentSql;    private MappedStatement currentStatement;    @Override    public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {        Configuration configuration = ms.getConfiguration();        StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject,                                                                    RowBounds.DEFAULT, null, null);        BoundSql boundSql = ms.getBoundSql(parameterObject);        String sql = boundSql.getSql();        Statement stmt;        // 检查是否需要切换SQL        if (sql.equals(currentSql) && ms.equals(currentStatement)) {            // 相同SQL,复用Statement            int last = statementList.size() - 1;            stmt = statementList.get(last);        } else {            // 不同SQL,创建新Statement            currentSql = sql;            currentStatement = ms;            stmt = prepareStatement(handler);            statementList.add(stmt);            batchResultList.add(new BatchResult(ms, sql, parameterObject));        }        // 添加批处理        handler.parameterize(stmt);        handler.batch(stmt);        return BATCH_UPDATE_RETURN_VALUE;    }    @Override    public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {        List<BatchResult> results = new ArrayList<>();        try {            for (int i = 0, n = statementList.size(); i < n; i++) {                Statement stmt = statementList.get(i);                BatchResult batchResult = batchResultList.get(i);                try {                    if (!isRollback) {                        // 执行批处理                        int[] updateCounts = stmt.executeBatch();                        batchResult.setUpdateCounts(updateCounts);                    }                    results.add(batchResult);                } catch (SQLException e) {                    throw new BatchExecutorException("Error updating database. Cause: " + e, e, batchResult);                }            }            return results;        } finally {            // 清空缓存            statementList.clear();            batchResultList.clear();            currentSql = null;            currentStatement = null;        }    }}

2.6 CachingExecutor缓存执行器

CachingExecutor是Executor的装饰器,在底层Executor之上增加了二级缓存功能:

public class CachingExecutor implements Executor {    private final Executor delegate;    private final TransactionalCacheManager tcm = new TransactionalCacheManager();    @Override    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,                            ResultHandler resultHandler) throws SQLException {        // 1. 获取BoundSql        BoundSql boundSql = ms.getBoundSql(parameter);        // 2. 创建CacheKey        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);        // 3. 查询缓存        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);    }    @Override    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,                            ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {        // 1. 检查二级缓存        Cache cache = ms.getCache();        if (cache != null) {            // 刷新缓存(如果需要)            flushCacheIfRequired(ms);            // 检查缓存是否命中            if (ms.isUseCache() && resultHandler == null) {                List<E> list = (List<E>) tcm.getObject(cache, key);                if (list != null) {                    return list;                }            }        }        // 2. 缓存未命中,委托给底层Executor执行        List<E> list = delegate.<E>query(ms, parameter, rowBounds, resultHandler, key, boundSql);        // 3. 将结果放入二级缓存        if (cache != null) {            tcm.putObject(cache, key, list);        }        return list;    }}

三、SQL执行流程

SQL的执行流程是Executor的核心工作流程。

MyBatis SQL执行模块详解nerror="javascript:errorimg.call(this);">

SQL执行流程

3.1 完整执行流程

以查询操作为例,完整的SQL执行流程如下:

// 1. SqlSession调用Executorpublic <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {    try {        // 1.1 获取MappedStatement        MappedStatement ms = configuration.getMappedStatement(statement);        // 1.2 调用Executor执行查询        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);    } catch (Exception e) {        throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);    }}// 2. Executor执行查询@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {    // 2.1 获取BoundSql    BoundSql boundSql = ms.getBoundSql(parameter);    // 2.2 创建CacheKey    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);    // 2.3 执行查询    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);}// 3. 检查一级缓存@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds,                        ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {    List<E> list;    // 3.1 检查一级缓存    if (resultHandler == null) {        list = (List<E>) localCache.getObject(key);    }    if (list != null) {        return list;    }    // 3.2 缓存未命中,查询数据库    list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);    return list;}// 4. 查询数据库private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds,                                     ResultHandler resultHandler, CacheKey key, BoundSql boundSql) {    List<E> list;    // 4.1 占位缓存,处理循环依赖    localCache.putObject(key, EXECUTION_PLACEHOLDER);    try {        // 4.2 执行查询        list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);    } finally {        // 4.3 移除占位符        localCache.removeObject(key);    }    // 4.4 将结果放入一级缓存    localCache.putObject(key, list);    // 4.5 处理延迟加载    if (ms.getConfiguration().isLazyLoadingEnabled()) {        if (deferredLoads != null && !deferredLoads.isEmpty()) {            deferredLoads.clear();        }    }    return list;}// 5. 执行实际查询protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds,                                       ResultHandler resultHandler, BoundSql boundSql) throws SQLException;

3.2 StatementHandler的作用

StatementHandler负责Statement的创建、参数设置和SQL执行:

public interface StatementHandler {    // 准备Statement    Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException;    // 参数化Statement    void parameterize(Statement statement) throws SQLException;    // 执行查询    <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;    // 执行更新    int update(Statement statement) throws SQLException;    // 批处理    void batch(Statement statement) throws SQLException;    // 获取BoundSql    BoundSql getBoundSql();}

3.3 ResultSetHandler的作用

ResultSetHandler负责将ResultSet映射为Java对象:

public interface ResultSetHandler {    // 处理结果集    <E> List<E> handleResultSets(Statement stmt) throws SQLException;    // 处理游标结果集    <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;    // 处理输出参数    void handleOutputParameters(CallableStatement cs) throws SQLException;}

四、缓存管理机制

MyBatis提供了两级缓存机制,有效提升查询性能。

MyBatis SQL执行模块详解nerror="javascript:errorimg.call(this);">

缓存管理机制

4.1 一级缓存(Local Cache)

一级缓存是SqlSession级别的缓存,默认开启,作用域是当前SqlSession:

public class PerpetualCache implements Cache {    private final String id;    private final Map<Object, Object> cache = new HashMap<>();    @Override    public void putObject(Object key, Object value) {        cache.put(key, value);    }    @Override    public Object getObject(Object key) {        return cache.get(key);    }    @Override    public Object removeObject(Object key) {        return cache.remove(key);    }    @Override    public void clear() {        cache.clear();    }}

一级缓存的特点:

1、作用域:SqlSession级别2、生命周期:与SqlSession相同,SqlSession关闭时缓存清空3、缓存Key:由MappedStatement ID、参数SQL、分页参数等组成4、自动失效:执行增删改操作时,一级缓存会自动清空

4.2 二级缓存(Global Cache)

二级缓存是Mapper级别的缓存,需要手动配置,作用域是Namespace:

<!-- 在Mapper XML中配置二级缓存 --><cache eviction="LRU" flushInterval="60000" size="1024" readonly="true"/>

二级缓存的特点:

1、作用域:Namespace(Mapper)级别2、生命周期:应用级别,直到应用关闭3、跨Session共享:多个SqlSession可以共享4、配置灵活:可以自定义缓存策略

4.3 缓存Key的构建

CacheKey由多个元素组成,确保缓存键的唯一性:

@Overridepublic CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {    CacheKey cacheKey = new CacheKey();    // 1. MappedStatement ID    cacheKey.update(ms.getId());    // 2. 分页参数    cacheKey.update(rowBounds.getOffset());    cacheKey.update(rowBounds.getLimit());    // 3. SQL语句    cacheKey.update(boundSql.getSql());    // 4. 参数值    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();    TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();    for (ParameterMapping parameterMapping : parameterMappings) {        String propertyName = parameterMapping.getProperty();        Object value;        if (boundSql.hasAdditionalParameter(propertyName)) {            value = boundSql.getAdditionalParameter(propertyName);        } else if (parameterObject == null) {            value = null;        } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {            value = parameterObject;        } else {            metaObject metaObject = configuration.newmetaObject(parameterObject);            value = metaObject.getValue(propertyName);        }        cacheKey.update(value);    }    // 5. Environment ID    if (configuration.getEnvironment() != null) {        cacheKey.update(configuration.getEnvironment().getId());    }    return cacheKey;}

4.4 缓存装饰器模式

MyBatis使用装饰器模式实现缓存功能的增强:

// 基础缓存Cache cache = new PerpetualCache("myCache");// 添加LRU淘汰策略cache = new LruCache(cache);// 添加定时刷新cache = new ScheduledCache(cache);// 添加序列化支持cache = new SerializedCache(cache);// 添加日志记录cache = new LoggingCache(cache);// 添加同步支持cache = new SynchronizedCache(cache);

4.5 缓存使用示例

// 一级缓存示例SqlSession session = sqlSessionFactory.openSession();try {    UserMapper mapper = session.getMapper(UserMapper.class);    // 第一次查询,访问数据库    User user1 = mapper.selectById(1L);    // 第二次查询,从一级缓存获取    User user2 = mapper.selectById(1L);    // user1 == user2,同一对象} finally {    session.close();}// 二级缓存示例SqlSession session1 = sqlSessionFactory.openSession();SqlSession session2 = sqlSessionFactory.openSession();try {    UserMapper mapper1 = session1.getMapper(UserMapper.class);    UserMapper mapper2 = session2.getMapper(UserMapper.class);    // session1第一次查询,访问数据库    User user1 = mapper1.selectById(1L);    // session1提交,将数据写入二级缓存    session1.commit();    // session2查询,从二级缓存获取    User user2 = mapper2.selectById(1L);    // user1 equals user2(不同对象,但值相等)} finally {    session1.close();    session2.close();}

五、事务管理

事务管理是数据库操作的重要组成部分,Executor负责事务的创建、提交和回滚。

MyBatis SQL执行模块详解nerror="javascript:errorimg.call(this);">

事务管理

5.1 Transaction接口

Transaction是事务管理的顶层接口:

public interface Transaction {    // 获取数据库连接    Connection getConnection() throws SQLException;    // 提交事务    void commit() throws SQLException;    // 回滚事务    void rollback() throws SQLException;    // 关闭连接    void close() throws SQLException;    // 获取事务超时时间    Integer getTimeout() throws SQLException;}

5.2 事务隔离级别

MyBatis支持标准的事务隔离级别:

public enum IsolationLevel {    NONE(Connection.TRANSACTION_NONE),    READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),    READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),    REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),    SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);}

配置示例:

<settings>    <setting name="defaultTransactionIsolationLevel" value="READ_COMMITTED"/></settings>

5.3 事务管理流程

Executor的事务管理流程:

// 提交事务@Overridepublic void commit(boolean required) throws SQLException {    if (closed) {        throw new ExecutorException("Cannot commit, transaction is already closed");    }    // 1. 清空本地缓存    clearLocalCache();    // 2. 刷新批量操作    List<BatchResult> batchResults = flushStatements(true);    // 3. 提交事务    if (required) {        transaction.commit();    }    return batchResults;}// 回滚事务@Overridepublic void rollback(boolean required) throws SQLException {    if (closed) {        throw new ExecutorException("Cannot rollback, transaction is already closed");    }    try {        // 1. 清空本地缓存        clearLocalCache();        // 2. 刷新批量操作        flushStatements(true);        // 3. 回滚事务        if (required) {            transaction.rollback();        }    } finally {        if (required) {            // 4. 关闭事务            transaction.close();        }    }}

5.4 自动提交与手动提交

// 自动提交模式SqlSession session = sqlSessionFactory.openSession(true);try {    UserMapper mapper = session.getMapper(UserMapper.class);    mapper.insert(user);    // 无需手动提交,自动提交} finally {    session.close();}// 手动提交模式(默认)SqlSession session = sqlSessionFactory.openSession();try {    UserMapper mapper = session.getMapper(UserMapper.class);    mapper.insert(user);    // 需要手动提交    session.commit();} catch (Exception e) {    // 异常时回滚    session.rollback();    throw e;} finally {    session.close();}

5.5 Spring事务集成

在Spring环境中,通常使用Spring的事务管理:

@Service@Transactionalpublic class UserService {    @Autowired    private UserMapper userMapper;    public void updateUser(User user) {        // Spring管理事务,无需手动提交        userMapper.update(user);    }    @Transactional(propagation = Propagation.REQUIRED)    public void transfer(Long fromId, Long toId, BigDecimal amount) {        // 转账操作:同一事务        userMapper.decrease(fromId, amount);        userMapper.increase(toId, amount);    }}

六、批处理机制

批处理可以显著提升批量操作的性能。

MyBatis SQL执行模块详解nerror="javascript:errorimg.call(this);">

批处理机制

6.1 批处理配置

使用批处理需要指定ExecutorType:

// 创建批处理SqlSessionSqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);try {    UserMapper mapper = session.getMapper(UserMapper.class);    // 批量插入    for (User user : userList) {        mapper.insert(user);    }    // 刷新并执行批处理    session.flushStatements();    // 提交事务    session.commit();} finally {    session.close();}

6.2 批处理原理

BatchExecutor的工作原理:

1、SQL缓存:相同SQL复用Statement2、参数累积:多次调用addBatch()3、批量执行:调用executeBatch()4、结果返回:返回每条SQL的执行结果
@Overridepublic int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {    Configuration configuration = ms.getConfiguration();    StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject,                                                                RowBounds.DEFAULT, null, null);    BoundSql boundSql = ms.getBoundSql(parameterObject);    String sql = boundSql.getSql();    Statement stmt;    // 检查是否可以复用Statement    if (sql.equals(currentSql) && ms.equals(currentStatement)) {        stmt = statementList.get(statementList.size() - 1);    } else {        stmt = prepareStatement(handler);        statementList.add(stmt);        batchResultList.add(new BatchResult(ms, sql, parameterObject));        currentSql = sql;        currentStatement = ms;    }    // 参数化并添加到批处理    handler.parameterize(stmt);    handler.batch(stmt);    return BATCH_UPDATE_RETURN_VALUE;}

6.3 批处理性能优化

批处理的性能优化建议:

1、合理控制批次大小:避免一次性提交过多SQL2、使用BatchExecutor:批量操作时使用批处理执行器3、关闭自动提交:手动控制事务提交4、合理使用flushStatements:控制批处理执行时机
// 分批处理示例SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);try {    UserMapper mapper = session.getMapper(UserMapper.class);    int batchSize = 1000;    List<List<User>> batches = Lists.partition(userList, batchSize);    for (List<User> batch : batches) {        for (User user : batch) {            mapper.insert(user);        }        // 每批次刷新一次        session.flushStatements();        session.clearCache();    }    session.commit();} finally {    session.close();}

6.4 批处理返回结果

批处理返回的是每条SQL影响的行数:

List<BatchResult> results = session.flushStatements();for (BatchResult result : results) {    int[] updateCounts = result.getUpdateCounts();    for (int count : updateCounts) {        System.out.println("影响行数: " + count);    }}

6.5 批处理注意事项

1.Statement限制:数据库对PreparedStatement数量有限制2.内存占用:大量SQL会占用较多内存3.错误处理:批处理中某条SQL失败,需要特别处理4.日志输出:批处理日志可能较多,建议适当调整日志级别

七、最佳实践

7.1 Executor选择建议

场景

推荐Executor

说明

一般查询

SIMPLE

默认选择,每次创建新Statement

重复查询多

REUSE

复用Statement,减少创建开销

批量操作

BATCH

显著提升批量操作性能

启用二级缓存

CACHING

在其他Executor基础上增加缓存

7.2 性能优化建议

1、合理使用缓存:根据业务特点选择缓存级别2、批量操作优化:大量数据修改使用BatchExecutor3、及时清理缓存:避免缓存数据过期4、控制事务范围:事务尽量小,减少锁竞争5、使用连接池:避免频繁创建连接

7.3 常见问题解决

问题1:一级缓存未生效

// 问题代码UserMapper mapper = session.getMapper(UserMapper.class);User user1 = mapper.selectById(1L);User user2 = mapper.selectById(1L);// user1 != user2,缓存未生效// 原因:两次查询不在同一SqlSession// 解决:确保在同一个SqlSession中查询

问题2:二级缓存脏数据

<!-- 解决方案:设置刷新间隔 --><cache eviction="LRU" flushInterval="60000" size="1024" readonly="false"/>

问题3:批处理内存溢出

// 解决方案:分批处理int batchSize = 1000;for (int i = 0; i < totalSize; i += batchSize) {    List<User> batch = userList.subList(i, Math.min(i + batchSize, totalSize));    processBatch(session, batch);    session.flushStatements();    session.clearCache();}

八、总结

MyBatis的SQL执行模块是整个框架的核心执行引擎,通过精心设计的Executor体系,实现了高效的SQL执行、灵活的缓存管理、可靠的事务控制和强大的批处理能力。

打赏
0相关评论
热门搜索排行
精彩图片
友情链接
声明:本站信息均由用户注册后自行发布,本站不承担任何法律责任。如有侵权请告知立立即做删除处理。
违法不良信息举报邮箱:115904045
头条快讯网 版权所有
中国互联网举报中心