A very simple solution for a queryWithRowHandler when fails due to 
OutOfMemoryError
-----------------------------------------------------------------------------------

                 Key: IBATIS-474
                 URL: https://issues.apache.org/jira/browse/IBATIS-474
             Project: iBatis for Java
          Issue Type: Wish
          Components: DAO
            Reporter: haruhiko nishi
            Priority: Trivial


 A simple solution to queryWithRowHandler gets OutOfMemoryError when it needs 
to process very large results. Works only if the primary key of the target 
table is numeric sequence.

 public void queryWithRowHandler(String id,NumericRange numericRange,RowHandler 
rowHandler,boolean continueWithError){
        DaoException exception=null;
        boolean retryOccured=false;
        int retryCount=retry_count;
        int retryInterval=retry_interval;
        for(;;){
            do{
                if(retryOccured||numericRange.hasNextRange()){
                    try{
                        daoManager.startTransaction();
                        super.queryWithRowHandler(id,numericRange,rowHandler);
                        daoManager.commitTransaction();
                        if(retryOccured){
                            retryOccured=!retryOccured;
                            retryCount=retry_count;
                        }
                    }catch(DaoException e){
                        exception=e;
                        retryOccured=true;
                        try{
                            Thread.sleep(retryInterval * 1000);
                        }catch(InterruptedException ignored){}
                    }finally{
                        daoManager.endTransaction();
                    }
                }else
                    return;
            }while(retryOccured && (--retryCount>0));
            if(retryCount==0){
                retryOccured=false;
                retryCount=retry_count;
               if(!continueWithError) 
                   throw exception;

            }
        }
    }

public class NumericRange {
    private final ReentrantLock mainLock = new ReentrantLock();
    private int range;
    private volatile int max;
    private volatile int min;
    private AtomicInteger nextMax;
    
    public NumericRange(int range,int max){
        if(range<0||max<0)
            throw new IllegalArgumentException();
        this.range=range;
        this.nextMax=new AtomicInteger(max);
    }
    
    protected final boolean hasNextRange(){
        int n,tmpMax;
        mainLock.lock();
        try{
            max=nextMax.get();
            if((n=max - range -1)> 0)
                nextMax.set(n);
            else
                nextMax.set(0);
            min=Math.max(0,max-range);
            return max>0;
        }finally{
           mainLock.unlock();
        }
    }
    
    public int getMin(){
        return this.min;
    }
    
    public int getMax(){
        return this.max;
    }
}

    <select id="queryWithRowHandler" resultClass="member" 
parameterClass="NumericRange">
        SELECT *
        FROM TABLE WHERE primary_key BETWEEN #min# and #max#
    </select>

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to