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

高并发测试时,出现RuntimeException #56

Closed
xzhiwei opened this issue May 22, 2017 · 1 comment
Closed

高并发测试时,出现RuntimeException #56

xzhiwei opened this issue May 22, 2017 · 1 comment

Comments

@xzhiwei
Copy link

xzhiwei commented May 22, 2017

使用版本:4.1.6
说明:查看5.0.1版本源码,该部分代码没变,应该也可以重现该bug
异常现场

### Error querying database.  Cause: java.lang.RuntimeException: 无法处理该类型[class com.github.pagehelper.sqlsource.PageDynamicSqlSource]的SqlSource
### Cause: java.lang.RuntimeException: 无法处理该类型[class com.github.pagehelper.sqlsource.PageDynamicSqlSource]的SqlSource
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:79)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:447)
	at com.sun.proxy.$Proxy72.selectList(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:231)
	at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:128)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:68)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:53

重现
在启一个线程池,进行同一个分页查询操作时,出现RuntimeException,无法处理该类型PageDynamicSqlSource

所用代码如下:

    @Test
    public void search() throws Exception {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i = 0;i<10;i++) {
            executorService.submit(new Runnable() {
                @Override
                public void run() {
                    Object result = testService.search(1, new Random().nextInt(1000));
                    logger.info(JSONObject.toJSONString(result));
                }
            });
        }
        executorService.shutdown();
        while(true){
            if(executorService.isTerminated()){
                break;
            }
            Thread.sleep(100);
        }
    }

异常分析
在SqlUtils方法中有以下处理:

     //判断并处理为PageSqlSource
        if (!isPageSqlSource(ms)) {
            processMappedStatement(ms);
        }

其中:
processMappedStatement方法为:

public void processMappedStatement(MappedStatement ms) throws Throwable {
        SqlSource sqlSource = ms.getSqlSource();
        MetaObject msObject = SystemMetaObject.forObject(ms);
        SqlSource pageSqlSource;
        if (sqlSource instanceof StaticSqlSource) {
            pageSqlSource = new PageStaticSqlSource((StaticSqlSource) sqlSource);
        } else if (sqlSource instanceof RawSqlSource) {
            pageSqlSource = new PageRawSqlSource((RawSqlSource) sqlSource);
        } else if (sqlSource instanceof ProviderSqlSource) {
            pageSqlSource = new PageProviderSqlSource((ProviderSqlSource) sqlSource);
        } else if (sqlSource instanceof DynamicSqlSource) {
            pageSqlSource = new PageDynamicSqlSource((DynamicSqlSource) sqlSource);
        } else if(sqlSource instanceof PageDynamicSqlSource) {
            pageSqlSource = sqlSource;
        }else {
            throw new RuntimeException("无法处理该类型[" + sqlSource.getClass() + "]的SqlSource");
        }
        msObject.setValue("sqlSource", pageSqlSource);
        //由于count查询需要修改返回值,因此这里要创建一个Count查询的MS
        msCountMap.put(ms.getId(), MSUtils.newCountMappedStatement(ms));
    }

由于processMappedStatement是非线程安全的方法,虽然前面进行过if判断,进入这个方法体后sqlSource对象还是有可能是处理过的PageSqlSource,此时instanceof 判断失败,抛出RuntimeException

建议订正
在条件判断最后,再进行一次PageSqlSource的判断,如果是,直接返回:

else if(sqlSource instanceof PageSqlSource){
    pageSqlSource  = sqlSource ;
}else {
            throw new RuntimeException("无法处理该类型[" + sqlSource.getClass() + "]的SqlSource");
 }
@abel533
Copy link
Collaborator

abel533 commented May 22, 2017

5.0.0+不使用sqlsource进行处理了,所以应该没有这个问题,建议你试试最新版本。

@abel533 abel533 closed this as completed May 30, 2017
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