Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

框架层能否增加查询数量的限制? #3436

Open
mwjmwj opened this issue Mar 19, 2025 · 1 comment
Open

框架层能否增加查询数量的限制? #3436

mwjmwj opened this issue Mar 19, 2025 · 1 comment

Comments

@mwjmwj
Copy link

mwjmwj commented Mar 19, 2025

问题:
在使用mybatis查询数据时,如果sql编写不得当,会出现全表扫数据,数据很多的话

容易出现内存溢出的问题,能否在 statementid层 对查询的总数做一个可配置的校验

解决思路:
例如:

<select id="query" resultType="java.util.HashMap" maxCountSize="10000"> (也可做成读上下文动态配置,可实时修改)

使用的位置:

org.apache.ibatis.executor.resultset.DefaultResultSetHandler

private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap,
    ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
    DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
    ResultSet resultSet = rsw.getResultSet();
    skipRows(resultSet, rowBounds);
    int queryIndex = 0;
    while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
        queryIndex++;
        if (queryIndex > 当前sql语句配置的最大值) {
                    // 弹出报错,不然继续解析最终会导致oom
            throw new RuntimeException("query Size has large greate 10000!");
        }
        ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
        Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
        storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
    }

}
@harawata
Copy link
Member

Hello @mwjmwj ,

No. MyBatis does not provide such feature.

Checking the result size after retrieving ResultSet isn't efficient.
JDBC provides java.sql.Statement#setMaxRows(), but its efficiency depends on the db/driver implementation.
The best way is to limit the number of returned rows in SQL using FETCH NEXT x ROWS ONLY or LIMIT x.
See this answer: https://stackoverflow.com/a/61140502/1261766

If you expect an exception, for some reason, you may have to get an extra row and check the result size. e.g.

select * from some_table fetch next 10001 rows only
List results = yourMapper.select();
if (results.size() > 10000) {
  throw new RuntimeException("query Size has large greate 10000!");
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants