카테고리 없음

[JDBC] PreparedStatement 사용 장단점 및 예시

ForA 2019. 7. 10. 19:04
728x90

Statement

(java.sql.Statement)

: executeQuery("DQL문"), excecuteUpdate("DML문")메소드를 실행하는 시점에 파라미터로 SQL문을 DB에 전달한다.

  • 장점 : 사용된 SQL문 전체를 명확히 알 수 가 있어서 디버깅이 쉽다.
  • 단점 : 조건값이 틀린 많은 수의 SQL문을 반복 실행하게 되는 경우, DB서버에서 모두 새롭게 PARSING되어야 하므로 부하가 생길수 있다. SQL Injection에 취약.
    //SQL injection 예)
    //데이터 전달: a' 1=1 --
    SELECT count(*) FROM membership WHERE id = 'a' or 1=1 --' AND pass='1234';

PreparedStatement

(java.sql.PreparedStatement)

: 커넥션에서 생성하면서 SQL문이 DB에 전송되어진다. Statement클래스를 상속하고 있음

  • 장점: bind변수를 사용하여 DB서버에서 파싱된 SQL을 재사용하게 만듬으로, 반복적인 다량의 SQL수행시 성능상 이득이 있다. 반복 루프를 통해서 하나의 SQL문에 변수값만 입력하며 반복 실행 할 수 있음.
    ★ SQL injection예방의 방법이 될 수 있다.
    따옴표와 콤마의 조합 그리고 자료형에 신경쓰지 않아도 됨.
    사용자가 입력한 (sql구문) 데이터가 변경될 염려가 없다.
  • 단점: 오류발생 시, 변수에 입력되는 값을 알 수 없어서 디버깅이 어렵다.
    int cnt;

    String sql = "INSERT INTO person VALUES (?,?,?,?)"; //?: 바인드변수
    stmt = conn.prepareStatement(sql); //(데이터가 빠진) sql문 전송
        //?의 수만큼 설정
    //stmt.set자료형(물음표인덱스1~,설정데이터);// ?(바인드변수)에 대한 데이터 설정
        stmt.setInt(1, 1);
        stmt.setString(2, name);
        stmt.setInt(3, 13);
        stmt.setString(4, "학생");

    rs = stmt.executeUpdate(); // rs: 전역변수에 선언한 ResultSet
    // 주의: 이미 prepareStatement에서 sql문을 전송했으므로 execute() 메소드 내에 sql 기입하면 안됨.
    if(rs.next()) {
        cnt= rs.get자료형("컬럼명");
    }
    return cnt; //메소드 리턴

예제

//(이름패턴)회원 정보 조회
public ArrayList<MembershipVO> findByName(String name) {
    connect(); //드라이브 연결 메소드
    ArrayList<MembershipVO> list = new ArrayList<MembershipVO>();
    try {
        String sql="SELECT id,name,ssn1,ssn2,phone,addr,job FROM membership "
                + "WHERE name LIKE ?"; //setString 해준 순간 ''가 자동 생성되기에 ''표기없이 ?만 기재
        stmt = conn.prepareStatement(sql);//sql문 전송
          stmt.setString(1, "%"+name+"%");//'%홍%'
        rs=stmt.executeQuery();//sql문 실행요청. ResultSet rs

        while(rs.next()) {//행얻기
            //열데이터 얻기
            MembershipVO vo = new MembershipVO();
            //7개의 관련있는 속성데이터를 묶어주기 위해 사용.
            vo.setId(rs.getString("id"));
            vo.setName(rs.getString("name"));
            vo.setSsn1(rs.getInt("ssn1"));
            vo.setSsn2(rs.getInt("ssn2"));
            vo.setPhone(rs.getString("phone"));
            vo.setAddr(rs.getString("addr"));
            vo.setJob(rs.getString("job"));            
            list.add(vo);
        }//while
    } catch (SQLException e) {
        e.printStackTrace();
    }finally {
        disconnect(); //드라이브 비연결 메소드
    }
    return list;
}//findAll