Recent Posts
Recent Comments
Link
01-07 06:48
Today
Total
관리 메뉴

삶 가운데 남긴 기록 AACII.TISTORY.COM

ORA-01704: JAVA ORACLE JDBC로 4000자 이상 CLOB 데이터 INSERT, UPDATE 예제 본문

DEV&OPS/Java

ORA-01704: JAVA ORACLE JDBC로 4000자 이상 CLOB 데이터 INSERT, UPDATE 예제

ALEPH.GEM 2024. 12. 30. 19:23

 

 

 ORA-01704

JAVA로 ORACLE DBMS에 JDBC로 프로그램을 작성할 때,

문자열이 4000자가 넘어가면 일반 String statement로 insert/update시  ORA-01704를 발생시키며 안됩니다.

 

그럴 때 java.sql.Clob 클래스를 사용해서 preparedStatement.setClob()를 써서 구현하면 CLOB 데이터를 insert/update 할 수 있습니다.

 

예제는 아래와 같습니다.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Clob;

public class ClobExample {

    private static final String JDBC_URL = "jdbc:oracle:thin:@localhost:1521:yourdb";
    private static final String USERNAME = "yourUsername";
    private static final String PASSWORD = "yourPassword";

    public static void main(String[] args) {
        Connection connection = null;

        try {
            // 1. 데이터베이스 연결
            connection = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);

            // 2. CLOB 삽입 예제
            String clobData = generateLargeClobData(); // 큰 CLOB 데이터 생성
            insertClobData(connection, clobData);

            // 3. CLOB 업데이트 예제
            String updatedClobData = generateUpdatedClobData(); // 업데이트할 CLOB 데이터 생성
            updateClobData(connection, updatedClobData);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 4. 연결 종료
            if (connection != null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private static void insertClobData(Connection connection, String clobData) throws SQLException {
        String insertQuery = "INSERT INTO your_table (clob_column) VALUES (?)";
        try (PreparedStatement preparedStatement = connection.prepareStatement(insertQuery)) {
            // CLOB 데이터를 PreparedStatement에 설정
            Clob clob = connection.createClob();
            clob.setString(1, clobData);
            preparedStatement.setClob(1, clob);
            // 쿼리 실행
            preparedStatement.executeUpdate();
        }
    }

    private static void updateClobData(Connection connection, String updatedClobData) throws SQLException {
        String updateQuery = "UPDATE your_table SET clob_column = ? WHERE your_condition";
        try (PreparedStatement preparedStatement = connection.prepareStatement(updateQuery)) {
            // CLOB 데이터를 PreparedStatement에 설정
            Clob clob = connection.createClob();
            clob.setString(1, updatedClobData);
            preparedStatement.setClob(1, clob);
            // 쿼리 실행
            preparedStatement.executeUpdate();
        }
    }

    private static String generateLargeClobData() {
        // 큰 CLOB 데이터를 생성하는 코드 작성
        return "엄청나게 긴 4000자 이상 CLOB Data...";
    }

    private static String generateUpdatedClobData() {
        // 업데이트할 CLOB 데이터를 생성하는 코드 작성
        return "엄청나게 긴 4000자 이상 Updated CLOB Data...";
    }
}

 

 

또는 아주 긴 문자열을 등분하여 insert/update 해도 됩니다. 

 

String을 10등분 하는 예제

public class LongStringDivider {
    public static void main(String[] args) {
        // 아주 긴 문자열 생성 
        String longString = "이것은 굉장히 길어서 10등분 해서 나누어질 String 입니다...";

        // 문자열의 길이 계산
        int length = longString.length();

        // 등분할 개수 여기서는 10등분
        int parts = 10;

        // 등분한 문자열 출력
        for (int i = 0; i < parts; i++) {
            int startIndex = i * length / parts;
            int endIndex = (i + 1) * length / parts;
            String part = longString.substring(startIndex, endIndex);
            System.out.println("Part " + (i + 1) + ": " + part);
        }
    }
}

 

 

그러고 나서 아래처럼 쿼리를 TO_CLOB() 함수를 써서 문자열 연결 연산자 || 로 연결해서 쿼리를 작성하면 됩니다.

UPDATE your_table SET clob_column = TO_CLOB('아주 긴 String') || TO_CLOB('엄청나게 긴 String') WHERE your_condition

 

 

또 다른 방법으로는 2000 글자씩 나누는 방법도 있습니다.

import java.util.ArrayList;
import java.util.List;

public class StringSplitter {

    private static final int CHUNK_SIZE = 2000;

    public static List<String> splitString(String input) {
        List<String> result = new ArrayList<>();
        int length = input.length();
        for (int i = 0; i < length; i += CHUNK_SIZE) {
            result.add(input.substring(i, Math.min(length, i + CHUNK_SIZE)));
        }
        return result;
    }

    public static void main(String[] args) {
        String longString = "This is a very long string..."; 
        List<String> parts = splitString(longString);
        
        for (int i = 0; i < parts.size(); i++) {
            System.out.println("Part " + (i + 1) + ": " + parts.get(i));
        }
    }
}

이렇게 String을 나눈 뒤 위 처럼 TO_CLOB('2000자') || TO_CLOB('2000자') 처럼 연결하는 방법도 있습니다.

 

 

두 개의 CLOB데이터를 insert 하는 예제

한번에 두 개 이상의 CLOB데이터를 setCharacterStream() 을 이용해서 insert할 수 있습니다.

// 1. 데이터베이스 연결
connection = DriverManager.getConnection(jdbcUrl, username, password);

// 2. 두 개의 CLOB 열이 있는 테이블의 INSERT SQL 준비
String sql = "INSERT INTO clob_table (id, clob_column1, clob_column2) VALUES (?, ?, ?)";
pstmt = connection.prepareStatement(sql);

// 3. CLOB 데이터 준비
int id = 1;
String largeText1 = "이것은 첫 번째 CLOB 데이터입니다.";
String largeText2 = "이것은 두 번째 CLOB 데이터입니다.";

// 4. PreparedStatement에 값 설정
pstmt.setInt(1, id);
pstmt.setCharacterStream(2, new java.io.StringReader(largeText1), largeText1.length());
pstmt.setCharacterStream(3, new java.io.StringReader(largeText2), largeText2.length());

// 5. 쿼리 실행
int rowsInserted = pstmt.executeUpdate();

 

 

 

 

 

 

728x90