mybatisクエリー大量データメモリオーバーフロー解決方法

4933 ワード

通常mybatisを使用する場合はメモリの問題は考慮されていませんが、今日はクエリーが必要なデータ量が多く、システムoomを直接招くことがあります.そのため、クエリーが大量に必要なsqlについて以下のように修正しました.
ダイレクトコード
    @Autowired
    private SqlSessionTemplate sqlSessionTemplate;


    @Test
    public void test() {
        MerchantOrderPushExample merchantOrderPushExample = new MerchantOrderPushExample();
        MerchantOrderPushExample.Criteria criteria = merchantOrderPushExample.createCriteria();
        criteria.andIdIsNotNull();
        merchantOrderPushExample.setOrderByClause(" id desc");
        HashMap param = new HashMap<>();
        param.put("oredCriteria", merchantOrderPushExample.getOredCriteria());
        param.put("orderByClause", merchantOrderPushExample.getOrderByClause());
        // param.put("limit",20);        
        sqlSessionTemplate.select("com.xws.business.mapper.MerchantOrderPushMapper.selectByExample", param, resultContext -> {
            MerchantOrderPush resultObject = (MerchantOrderPush) resultContext.getResultObject();
            System.out.println(JSON.toJSONString(resultObject));
        });
    }

ここではmybatisのフロークエリを使用しています.具体的な原理は、内部でResultContextを直接操作してデータを1つずつ取得し、handlerをコールバックするhandleResultメソッド処理です.
原理:
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException {
    DefaultResultContext resultContext = new DefaultResultContext();
    skipRows(rsw.getResultSet(), rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
    }
  }

  private void storeObject(ResultHandler> resultHandler, DefaultResultContext resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
    if (parentMapping != null) {
      linkToParents(rs, parentMapping, rowValue);
    } else {
      callResultHandler(resultHandler, resultContext, rowValue);
    }
  }
   
  //    
  @SuppressWarnings("unchecked" /* because ResultHandler> is always ResultHandler*/)
  private void callResultHandler(ResultHandler> resultHandler, DefaultResultContext resultContext, Object rowValue) {
    resultContext.nextResultObject(rowValue);
    ((ResultHandler) resultHandler).handleResult(resultContext);
  }

結果の比較:
図は上ではなく、非フロークエリを用いるメモリの使用時に線形に増加し、フロークエリを用いるメモリの使用は安定している.回避に成功しました.
また、mybatisフロークエリには、検証なしでbeanを注入し、springbootで@Configration方式を使用する方法もあります.


    
    


mapperでxmlのsqlにfetchSize="-21748483648",Integer.MIN_VALUE=-2147483648
static void testCursor1() throws UnexpectedInputException, ParseException, Exception {

        try {
            Map param = new HashMap();
            

            AccsDeviceInfoDAOExample accsDeviceInfoDAOExample = new AccsDeviceInfoDAOExample();
            accsDeviceInfoDAOExample.createCriteria().andAppKeyEqualTo("12345").andAppVersionEqualTo("5.7.2.4.5")
            .andPackageNameEqualTo("com.test.zlx");

            param.put("oredCriteria", accsDeviceInfoDAOExample.getOredCriteria());

            //     
            myMyBatisCursorItemReader.setParameterValues(param);
            
            //     
            myMyBatisCursorItemReader.open(new ExecutionContext());

            //            
            Long count = 0L;
            AccsDeviceInfoDAO accsDeviceInfoDAO;
            while ((accsDeviceInfoDAO = myMyBatisCursorItemReader.read()) != null) {

                System.out.println(JSON.toJSONString(accsDeviceInfoDAO));
                ++count;
                System.out.println(count);

            }
        } catch (Exception e) {
            System.out.println("error:" + e.getLocalizedMessage());
        } finally {

            // do some
            myMyBatisCursorItemReader.close();
        }

}



リファレンス
jdbcのフロークエリhttp://ifeve.com/mysq-stream-search/