批量操作时,如果用addBatch(),一次批量数据量太大,会出现Out of Memory的错误,解决方法就是以1W或2W条做一次execute(),但不commit,最后再commit

解决方案 »

  1.   

    DAO中批量数据的插入        PreparedStatement insPstmt = null;
            int rt = 0;        //sql文
            StringBuffer insSql = new StringBuffer();
            insSql.append(" INSERT INTO jsy_mst (" +
                            " jsycod, " +
                            " pstbng," +
                            " jsy001," +
                            " jsy002," +
                            " tkystrymd," +
                            " datetydte," +
                            " datetyttscod," +
                            " datetypgmcod)" +
                       " VALUES(?, ?, ?, ?, TO_DATE(?, 'YYYY/MM/DD'), now(), ?, ?)");        log.debug(insSql.toString());        try {
                insPstmt = conn.prepareStatement(insSql.toString());
                //SQL文参数设置
                for (Iterator it = jsyList.iterator(); it.hasNext();) {
            
                    JsymstInfo info = (JsymstInfo) it.next();
                
                    int i = 1;                // 
                    insPstmt.setString(i++, info.getJsycod());
                    insPstmt.setString(i++, info.getPstbng());
                    insPstmt.setString(i++, info.getJsy001());
                    insPstmt.setString(i++, info.getJsy002());
                    insPstmt.setString(i++, newLastStrYMD);
                    insPstmt.setString(i++, rysnoo);
                    insPstmt.setString(i++, pgmId);
                    insPstmt.addBatch();
                }
        
                //登录
                log.debug("begin to execute....size:" + jsyList.size());
                insPstmt.executeBatch();
                log.debug("execute finished");外部控制一次批量数据量
                conn = ConnectionMgr.getConnection();            ETC2100_00DAO dao = new ETC2100_00DAO();
                
                // 最新数据登录
                // 每一万件登录一次。(OutOfMemoryError防止)
                for (int i = 1; ; i++) {                List list = null;
                    boolean isBreak = false;                int cnt = 10000;
                    if (i * cnt >= upList.size()) {                    list = upList.subList((i-1) * cnt, upList.size());
                        isBreak = true;                } else {                    list = upList.subList((i-1) * cnt, i * cnt);
                    }                dao.batchInsertData(list, newStrYMD, info.getRysnoo(), pgmId, conn);                if (isBreak) {
                        break;
                    }
                }            // commit
                ConnectionMgr.commitConnection(conn);这是我的程序。connection都是统一取得,释放的。
      

  2.   

    for (Iterator it = jsyList.iterator(); it.hasNext();) {
            // 这是个死循环。除非你的jsyList只有1条记录或者为空
    应该改为
    Iterator it = jsyList.iterator(); 
    while(it.hasNext()){
      

  3.   

    其实你把List导成Iterator使用也会占用近似两倍的内存消耗。
    你可以通过List.get(int index)方法直接从List中获取JsymstInfo对象,这样可以去掉一个Iterator应该可以减少内存的消耗
      

  4.   

    不好意思弄错了
    for (Iterator it = jsyList.iterator(); it.hasNext();) {
            // 这是个死循环。除非你的jsyList只有1条记录或者为空
    这个不是死循环
    你的log显示到哪里就出现Out of Memory?是到这个循环的时候吗?
      

  5.   

    farmer0512(遡风而立者)兄弟谢谢你关注我的这个问题,希望大家一起探讨。
    我的log已经出去这个循环了,在
    //登录
    log.debug("begin to execute....size:" + jsyList.size());
    insPstmt.executeBatch();
    log.debug("execute finished");
    这三句话中,第一句log出来了,最后一句log一直没有出来,所以我想是登录数据库的时候的问题。
      

  6.   

    显示outOfMemeory不是在log里面,log里面走到登录执行之前的那句话后,后面什么都没有。
    outOfMemory是在画面上出现的。
      

  7.   

    你的tomcat设了JVM大小了吗?有可能真的是JVM的内存耗尽了。你试着通过更改tomcat的JAVA_OPTS设置增加JVM的大小看看。tomcat默认的JVM大小是128MB的,你可以增加到512MB看看还会出现OutOfMemoryError吗?。windows: %TOMCAT_HOME%/bin/catalina.bat  
    set JAVA_OPTS=-Xms512m -Xmx512mlinux: %TOMCAT_HOME%/bin/catalina.sh
    JAVA_OPTS=-Xms512m -Xmx512m
      

  8.   

    恩,我也看到过很多地方说增大JVM的内存。不过因为不确定是哪个内存不够的原因,所以没试着增大一下,先增大一下看看吧。