본문 바로가기

Java

clob

1. CLOB 컬럼 데이터 가져오기


지금 내가 쓰는 환경과 버젼이 다르다면 어떨지 본인도 확신할 수 없다.

워낙 이 녀석들이 버젼을 많이 타서...

근데 CLOB도 그냥 getString해오니까 가져오더라...


실험 데이터는

"가나다라마바사아자차카타파하 아야어여오요우유으이" * 1만줄 이다.


String test_clob = rs.getString("test_clob");


test_clob를 출력한 결과 아주 잘 나온다..-_-;;;


2. CLOB 컬럼 데이터 저장하기


  1) 일반 setString 이용


나는 보통 쿼리를 PreparedStatement 를 이용해서 사용하는데

이것같은 경우도 그냥 setString을 이용해서 넣어버리면 된다.


다만 문제...라기 보단 버그..인 것 같은데

위의 실험 데이터를 넣어본 결과

대략 200~300줄 마다 글자가 깨지는 줄이 생기곤 했다.


그래서 짐작하건데는 아마도 PreparedStatement의 setString을 통해서

DB로 데이터를 보내는 과정에서 데이터 양이 많은 경우

버퍼가 다 차서 그걸 비워내는 과정에서 원치않는 찌꺼기(?)가 생긴것이 아닐까 하는 추측을 해본다.

왜냐하면...한글은 2바이트니까.....


바꿔서 실험데이터를

"abcdefghijklmnopqrstuvwxyz 1234567890" * 1만줄 로 해본 결과

그냥 setString으로 데이터를 입력해도 깨짐없이 잘 들어간다.


이 부분은 톰캣 설정에서 SetBigStringTryClob=true 로 설정해도 같은 문제가 생긴다.


2) empty_clob()와 stream을 이용


1)의 문제 때문에 아무래도 CLOB 타입에 데이터를 넣는 것은

스트림으로 넣는 것이 좋지 않을까 하는 생각이 든다. 다음과 같이 말이다.


  conn = DBManager.getConnection();
  conn.setAutoCommit(false);

  StringBuffer sql = new StringBuffer();
  sql.append("insert into test values (empty_clob())");
  pstmt = conn.prepareStatement(sql.toString());
  pstmt.executeUpdate();
  DBManager.close(pstmt);

  sql = new StringBuffer();
  sql.append("select * from test");
  pstmt = conn.prepareStatement(sql.toString());
  rs = pstmt.executeQuery();
  if (rs != null)
  {
   if (rs.next())
   {
    Clob cl = rs.getClob("test_clob");
    // 스트림을 이용한 값 저장
    BufferedWriter writer = new BufferedWriter(cl.setCharacterStream(0));
    writer.write(tt.toString());     // tt가 실험데이터가 들은 변수
    writer.close();
   }
  }
  conn.commit();
  conn.setAutoCommit(true);
  DBManager.close(rs, pstmt);


* DBManager는 내가 만든 클래스이니 넘어가자~ ㅋㅋ


환경이 다른 경우에는

그냥 setString을 써도 잘 들어가지 않을까...하는 의혹도 있었지만

그것까지 일일이 테스트하는건 너무 귀찮아서리....


3) oracle.jdbc.OraclePreparedStatement 이용


왠만하면 추가의 import 없이 하려고 했는데 소스 코딩을 간결하게 해 주는

이 방법은 꽤나 좋다고 생각! oracle 자체에서 제공하는 OraclePreparedStatement이다.

뭐 대략 PreparedStatement를 상속한 것이겠지....응?? ㅋㅋ

이 중에서 쓰일 메소드는 setStringForClob()이다.

이걸로 넣으면 한글이 중간중간 쓰레기값이 들어가는 일 없이 잘 들어간다!! >ㅁ<)b


  import oracle.jdbc.*;

  ...

  OraclePreparedStatement opstmt = null;

  conn = DBManager.getConnection();

  StringBuffer sql = new StringBuffer();
  sql.append("insert into test values (?)");
  opstmt = (OraclePreparedStatement)conn.prepareStatement(sql.toString());
  opstmt.setStringForClob(1, tt.toString());   // tt가 실험데이터가 들은 변수
  opstmt.executeUpdate();
  if (opstmt != null) opstmt.close();

  ...


  주의해야 할 점은 OraclePreparedStatement를 사용하기 위해서는

  JNDI를 설정할때 javax.sql.DataSource가 아닌 oracle.jdbc.pool.OracleDataSource에서

  가져와야 한다는 것이다. 그렇지 않으면 ClassCastException 이 생긴다;.



[출처] JSP에서 Oracle CLOB Type 저장 및 읽기