当前位置: 代码网 > it编程>编程语言>Java > MyBatis SQL执行模块的使用及解读

MyBatis SQL执行模块的使用及解读

2026年01月02日 Java 我要评论
本文深入剖析mybatis的sql执行模块,带你全面理解executor执行器体系、缓存机制、事务管理和批处理原理。一、mybatis整体架构与sql执行模块在深入sql执行模块之前,我们先了解myb

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

一、mybatis整体架构与sql执行模块

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

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实现,以适应不同的使用场景。

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的核心工作流程。

3.1 完整执行流程

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

// 1. sqlsession调用executor
public <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执行查询
@override
public <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. 检查一级缓存
@override
public <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提供了两级缓存机制,有效提升查询性能。

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由多个元素组成,确保缓存键的唯一性:

@override
public 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负责事务的创建、提交和回滚。

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的事务管理流程:

// 提交事务
@override
public 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;
}

// 回滚事务
@override
public 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
@transactional
public 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);
    }
}

六、批处理机制

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

6.1 批处理配置

使用批处理需要指定executortype:

// 创建批处理sqlsession
sqlsession 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复用statement
2、参数累积:多次调用addbatch()
3、批量执行:调用executebatch()
4、结果返回:返回每条sql的执行结果
@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;

    // 检查是否可以复用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、合理控制批次大小:避免一次性提交过多sql
2、使用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、批量操作优化:大量数据修改使用batchexecutor
3、及时清理缓存:避免缓存数据过期
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)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com