'clob'에 해당되는 글 2건

  1. 2011.08.22 Oracle JDBC : "스트림이 이미 종료되었습니다" 혹은 "java.sql.SQLException: Stream has already been closed" 익셉션
  2. 2011.08.22 mybatis 에서 Oracle LONG, CLOB Select 시 에러날때 : getCLOB not implemented for class oracle.jdbc.driver.XXX

Oracle JDBC : "스트림이 이미 종료되었습니다" 혹은 "java.sql.SQLException: Stream has already been closed" 익셉션

Oracle JDBC 로 CLOB 나 LONG 같은, 값을 Stream 형태로 읽어야 하는 타입들을 Select 할때 발생하는 Exception 이다.

나같은 경우는 mybatis로 select 할때 쿼리문과 쿼리결과를 Log4j 로그로 찍었는데 시쭈구리하게도  logger 에서 ResultSet을 로그로 찍었기 때문에 나는 에러였다.

찍혀 있는 로그를 가만히 살펴보면 쿼리문이랑 ResultSet 결과가 먼저 쭉 찍힌뒤 그 뒤로 익셉션이 쭉 발생하고 있었다.
고말인 즉슨, 로거에서 찍을때는 정상적으로 값을 가져왔다는 말이된다.



가만 입다물고 생각해보면, 로거에서 ResultSet을 찍을려고 값을 가져오면서 Stream이 닫혀 버렸기 때문에 나는 에러 같았다.

기존 log4j.xml 설정은
<logger name="java.sql">
	<level value="debug" />
</logger>
 요렇게 되 있어서 java.sql 패키지에 포함된 모든클래스에서 발생하는 로그들을 다 찍게 되 있었다.




고것을
<logger name="java.sql.Connection">
	<level value="debug" />
</logger>

<logger name="java.sql.PreparedStatement">
	<level value="debug" />
</logger>
요래 바꿔서 ResultSet 에 대한 로그를 안찍게 바꾸니 해결되었다. 로그가 아예 필요없다면 다 지워도 되고~
나는 어떤 쿼리가 실행됬는가 까지는 꼭 알고 싶어서..



이것도 왠지 버그인것 같은 느낌이 문득 들지만 언젠가는 해결될것이라고 믿는다. 아니면 내가 잘못 쓰고 있는건가???? 

테스트 라이브러리 버전
mybatis :  3.0.6-SNAPSHOT.jar
oracle jdbc driver : ojdbc6.jar (11.2.0.2.0) 

mybatis 에서 Oracle LONG, CLOB Select 시 에러날때 : getCLOB not implemented for class oracle.jdbc.driver.XXX

MySQL 에서는 어떤지 잘 모르겠지만 아무튼 오라클에서는 Long Type이나 CLOB Type 컬럼을 select 할때 getCLOB() 가 구현되지 않았다면서 에러가 난다.

mybatis 에서 패치를 해줘야 되나 오라클에서 패치를 해 줘야 하나 쫌 거시기 하지만 아무튼 지금! 현재는 Long 을 가져오질 못한다 -_-

누군가는 패치를 해주긋지~

현재 라이브러리 버전은 요렇다.!
mybatis :  3.0.6-SNAPSHOT.jar
oracle jdbc driver : ojdbc6.jar (11.2.0.2.0)

지금 당장 하기는 해야 겠고 고쳐줄때 까지 기다릴수 없으니 해결하기 위해선 mybatis config 파일에서 LONG TYPE에 대해 TypeHandler 를 설정해 주면 된다.

mybatis config 파일
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
  "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<typeHandlers>
		<typeHandler handler="stove99.handler.CLOBHandler" javaType="String" jdbcType="LONGVARCHAR"/>
	</typeHandlers>
</configuration>
설정을 보면 대략 알겠지만 LONG 타입을 뜻하는 LONGVARCHAR jdbcType 에 대하여 처리할 핸들러를 설정해 주는 것이다.





TypeHandler 는 org.apache.ibatis.type.TypeHandler 인터페이스를 implements 해서 간단하게 메소드 3개를 구현하면 된다.
stove99.handler.CLOBHandler 의 소스는 다음과 같다.
package stove99.handler;

import java.io.StringReader;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

public class CLOBHandler implements TypeHandler{

	@Override
	// 파라메터 셋팅할때
	public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) 
           throws SQLException {
		String s = (String) parameter;
		StringReader reader = new StringReader(s);
		ps.setCharacterStream(i, reader, s.length());
	}

	@Override
	// Statement 로 SQL 호출해서 ResultSet 으로 컬럼값을 읽어올때
	public Object getResult(ResultSet rs, String columnName) throws SQLException {
		return rs.getString(columnName);
	}

	@Override
	// CallableStatement 로 SQL 호출해서 컬럼값 읽어올때
	public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
		return cs.getString(columnIndex);
	}
}

내 나름대로 이해하고 있는걸 적어놓은 것이니 미심쩍다는 사람들은 첨부파일 pdf 에서 14쪽을 참고하셈~

MyBatis-3.0.3-User-Guide.pdf

 
prev 1 next