浏览 3184 次
锁定老帖子 主题:ibatis 3.0 只创建不回收的BUG
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2009-11-10
最后修改:2009-11-10
IBatis.NET,不要相信它,内存疯狂泄漏 的bug....决定立即升级到最近版本 3.0.
前两天刚解决了结果今天又见一个BUG.:程序运行几分钟后,出现错误(oracle):打开游标数超过最大值 很明显,打开太多的Statement而没有关闭,不多说直接看源码(本人对于这种清理不干净的问题极其过敏) 一、问题 系统运行一段时间后,报(oracle):打开游标数超过最大值 二、原因:BATCH模式的executor对所有select操作产生的Statement未执行close操作。 SIMPLE的CRUD不存在此问题,但BATCH的所有select操作均未close。看三个关健方法代码: // BatchExecutor.java 文件 public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException { Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null); BoundSql boundSql = handler.getBoundSql(); String sql = boundSql.getSql(); Statement stmt; if (currentSql != null && sql.hashCode() == currentSql.hashCode() && sql.length() == currentSql.length()) { int last = statementList.size() - 1; // 添加 statement stmt = statementList.get(last); } else { Connection connection = transaction.getConnection(); stmt = handler.prepare(connection); currentSql = sql; statementList.add(stmt); batchResultList.add(new BatchResult(ms, sql, parameterObject)); } handler.parameterize(stmt); handler.batch(stmt); return BATCH_UPDATE_RETURN_VALUE; } public List doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { flushStatements(); Configuration configuration = ms.getConfiguration(); StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, rowBounds, resultHandler); Connection connection = transaction.getConnection(); Statement stmt = handler.prepare(connection); handler.parameterize(stmt); try{ // 在这里添加两行代码,以close相关Statement return handler.query(stmt, resultHandler); }finally{ closeStatement(stmt); } // add end. } // 这个方法在 commit 时会调用 public List<BatchResult> doFlushStatements() throws SQLException { List<BatchResult> results = new ArrayList<BatchResult>(); try { for (int i = 0, n = statementList.size(); i < n; i++) { Statement stmt = statementList.get(i); BatchResult batchResult = batchResultList.get(i); 。。。。。省 results.add(batchResult); } return results; } finally { for (Statement stmt : statementList) { // 在这里 close 批处理所用的 Statement closeStatement(stmt); } currentSql = null; statementList.clear(); batchResultList.clear(); } } 三.解决方法 上面代码已经给出相关说明。Batch模式对于更新操作会在commit时关闭,而 batch 模式对于select 操作是无效的,我们应该在做完select操作后直接将其close 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-09-27
你好,最近我读ibatis代码到此处,不是很明白doFlushStatements这个方法的用途,我发现只在BatchExecutor的query方法中调用了该方法,其他的executor类的query方法中没有对此调用,请告知?
|
|
返回顶楼 | |
发表时间:2010-09-27
也许是你看错了。
BatchExecutor.query-->flashStatements-->doFlashStatements BaseExecutor.commit-->flashStatements-->doFlashStatements |
|
返回顶楼 | |
发表时间:2010-09-27
嗯,我明白了。可是不解的是:ReuseExecutor.doQuery方法是否也要做同样的修改?
|
|
返回顶楼 | |