Developer/JAVA

Java에서의 SQL 데이터 처리: Statement, PreparedStatement ,ResultSet

단님 2024. 10. 30. 13:10
728x90
Statement와 PreparedStatement 비교

 

Statement와 PreparedStatement 클래스는 Java 애플리케이션에서 데이터베이스에 접근하여 SQL 쿼리를 작성하고 DB에 전달할 때 쓰는 클래스들로 다른 특성을 가지고 있다.

 

Statement

SQL 쿼리에서 변수를 직접 문자열로 결합하여 사용

String sql = "insert into student values(" + sno + ", '" + name + "', ...);";
st.executeUpdate(sql);

SQL 인젝션 공격에 취약하며, 매번 새롭게 SQL 구문을 컴파일하므로 성능이 떨어질 수 있다.

문자열 결합형식을 취하기 때문에 동적 쿼리 사용시 작성의 불편함이 있다.

 

PreparedStatement

?로 표기하는 바인딩 변수를 지원하여 쿼리의 복잡성을 줄이고, 보안과 성능을 개선한다.

String sql = "insert into student values(?, ?, ?, ...);";
PreparedStatement pst = cn.prepareStatement(sql);
pst.setInt(1, sno);
pst.setString(2, name);
pst.executeUpdate();

 

바인딩 변수를 사용하여 매개변수를 설정할 수 있어 가독성이 높아지고 SQL 인젝션 방지가 가능하다.

동일한 쿼리를 반복해서 사용할 때 쿼리를 캐싱하여 컴파일 비용을 절감하므로 성능이 향상된다.

 

따라서, 보안성과 성능 측면에서 PreparedStatement가 선호되며,
프레임워크에서도 기본적으로 이 방식을 지원하는 경우가 많다.

 

예시 ) PreparedStatement로 데이터 업데이트하기
public static void updatename(int sno, String name) {
    String sql = "update student set name=? where sno=?";
    
    try {
        PreparedStatement pst = cn.prepareStatement(sql); // SQL 문을 전달하며 PreparedStatement 객체 생성
        pst.setString(1, name); // 첫 번째 ?에 name 값 바인딩
        pst.setInt(2, sno);     // 두 번째 ?에 sno 값 바인딩
        
        // SQL 실행
        if (pst.executeUpdate() > 0) {
            System.out.println("업데이트 성공");
        } else {
            System.out.println("업데이트 실패");
        }
    } catch (Exception e) {
        System.out.println("updatename Exception: " + e.toString());
    }
}

 


 

SQL 실행 메서드 정리

 

Statement와 PreparedStatement에는 SQL 구문을 실행하기 위한 메서드가 있다.

 

executeQuery()

select 구문 실행.

인자로 SQL 문자열을 넣어주면 ResultSet 객체를 반환하여 쿼리 결과를 다룸.

ResultSet rs = st.executeQuery(sql);

 

executeUpdate()

insert, update, delete 구문 실행.

실행된 행의 개수(int)를 반환하므로, 반환값이 0이면 실행 실패를 의미한다.

int rowsAffected = pst.executeUpdate();

 

PreparedStatement의 메서드
setString ,setInt ....

SQL 실행 전에 매개변수를 설정.

몇번째 물음표에 인자를 넣을것인지 셋팅.

sql = "update student set name=? where sno=?";
		
try {
	pst=cn.prepareStatement(sql); // 생성하면서 sql문을 먼저 전달함.
	pst.setString(1, name);
	pst.setInt(2, sno); // 물음표 순서대로 넣을것
}

 

 


 

ResultSet

 

SQL 쿼리를 통해 조회된 결과는 ResultSet 객체에 저장되며, next() 메서드를 사용해 결과를 한 행씩 읽어들인다.

ResultSet :(결과 집합 : 레코들의 집합)→ 커서로 next 로 순회하여 읽고나면 사라짐 (1회성)

→ 가공또는 프론트단으로 보내기 위해 보관하기.

→역할별로 클래스를 나눠야 하는 구조가 나옴 : MVC모델

 

ResultSet의 주요 메서드
rs.getInt(columnIndex): 정수형 데이터를 열 순서로 가져옵니다.
rs.getString(columnLabel): 문자열 데이터를 열 이름으로 가져옵니다.
if (rs.next()) {
    do {
        System.out.print(rs.getInt(1) + " ");
        System.out.print(rs.getString("name") + " ");
        System.out.print(rs.getInt("age") + " ");
        // 필요한 모든 열 출력
    } while (rs.next());
} else {
    System.out.println("데이터 없음");
}

rs.next()를 사용하여 다음 행으로 이동하며, rs.getString("name") 등의 메서드를 통해 데이터를 가져온다.

ResultSet은 일회성 객체이므로 순회가 끝나면 사라지며,

필요한 경우 데이터를 저장해 프론트엔드에 전달하거나 가공할 수 있다.

 

rs.getInt(1) // 상수 사용 : 컬럼의 순번 입력
rs.getString("name") // 문자열 사용 : 컬럼의 이름 , 별칭이 있는경우 별칭으로 사용.