Web develop/JDBC_XML

[JDBC] Prepared Statement 사용법 및 사용예제

ForA 2019. 6. 19. 00:00
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