인생을 바꾸는 기록

java.sql.SQLException: Prepared or callable statement has more than 2000 parameter markers. 본문

spring

java.sql.SQLException: Prepared or callable statement has more than 2000 parameter markers.

phantom03 2020. 1. 28. 16:56

사용한 환경 : 전자정부프레임워크에 ibatis

문제)
파라미터가 2000개 넘어 가면 발생

<select id="lecture.select" parameterClass="java.util.Map" resultClass="ResultMap">
    	SELECT * 
    	FROM 
    		test 
    	WHERE 
    		1=1
			<isNotEmpty property="r_idx">
				AND r_idx IN
				<iterate property="r_idx" open="(" close=")" conjunction=",">
					#r_idx[]#
				</iterate>
			</isNotEmpty>
    </select>

요래 썼는데 r_idx가 2000개 넘어 가서 에러 발생

 

자료수집)

검색 해본 결과 드라이버 문제로 검색됨

아래는 문제되는 jTDS 드라이버 소스

if (params != null && params.size() > 255
     && connection.getPrepareSql() != TdsCore.UNPREPARED
     && procName != null) {
  int limit = 255; // SQL 6.5 and Sybase < 12.50
  if (connection.getServerType() == Driver.SYBASE) {
    if (connection.getDatabaseMajorVersion() > 12 ||
        connection.getDatabaseMajorVersion() == 12 &&
        connection.getDatabaseMinorVersion() >= 50) {
      limit = 2000; // Actually 2048 but allow some head room
    }
  } else {
    if (connection.getDatabaseMajorVersion() == 7) {
      limit = 1000; // Actually 1024
    } else if (connection.getDatabaseMajorVersion() > 7) {
      limit = 2000; // Actually 2100
    }
  }
  if (params.size() > limit) {
   throw new SQLException(
       Messages.get("error.parsesql.toomanyparams",
       Integer.toString(limit)),
       "22025");
  }
}

 

해결방법)

아래처럼 controller 에서 반복문으로 2000개씩 잘라줌

if(listMap.size() > 0) {
	    	for (int i = 0; i < listMap.size(); i++) {
	    		r_idx.add(listMap.get(i).get("r_idx").toString());
	    		if(i!=0 && i%1999 == 0){
	    			commandMap.put("r_idx", r_idx);
	    	    	seat.addAll(service.select(commandMap));
	    	    	r_idx = new ArrayList<String>();
	    		}else{
	    			if((i+1) == listMap.size()){
	    				commandMap.put("r_idx", r_idx);
		    	    	seat.addAll(service.select(commandMap));
		    	    	r_idx = new ArrayList<String>();
	    			}
	    		}
		    }
	    }