Save
public Member save(Member member) throws SQLException {
String sql = "insert into member(member_id,money) values(?,?)";
Connection con = null;
PreparedStatement pstmt = null;
try {
con = getConnection();
pstmt = con.prepareStatement(sql);
pstmt.setString(1, member.getMemberId());
pstmt.setInt(2, member.getMoney());
pstmt.executeUpdate();
return member;
} catch (SQLException e) {
log.error("DB error ", e);
throw e;
}finally {
close(con, pstmt, null);
}
}
실행 순서
1. getConnection()
: 앞써 작성했던 DriverManager가 드라이버를 찾아 커넥션을 가져온다.
2. con.prepareStatement(sql)
: DB에 전달할 SQL과 파라미터들을 준비한다.
위 처럼 PrepareStatement는 ?에 값을 지정하는 파라미터 바인딩 방법이다. Statement를 상속받았고, SQL Injection 공격을 방지할 수 있다.
3. pstm.executeUpdate()
: Statement를 통해 준비된 SQL을 커넥션을 통해 실제 DB에 전달한다. 반환값으로 영향받은 raw 수 를 반환한다.
4. close()
: try 절에서 에러가 발생하더라도 리소스를 반납할 수 있게끔 finally 구문에서 안전하게 반납해야한다.
리소스 반환
private void close(Connection con, Statement stmt, ResultSet rs) {
if (rs != null) {
try{
rs.close();
} catch (SQLException e) {
log.error("error", e);
}
}
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.error("error", e);
}
}
if (con != null) {
try{
con.close();
}catch (SQLException e) {
log.info("error", e);
}
}
}
리소스를 사용한 순서의 역순으로 안전하게 반납해야한다. 해당 리소스가 null일 경우 NPE 에러를 발생시켜 null을 체크하고 반납한다. 다만 반납하는 도중에 에러가 발생하는 경우 대처할 수 없는 방법이 없어 그냥 로그만 찍도록 했다.
find
con = getConnection();
pstmt = con.prepareStatement(sql);
pstmt.setString(1, memberId);
rs = pstmt.executeQuery();
if (rs.next()) {
Member member = new Member();
member.setMemberId(rs.getString("member_id"));
member.setMoney(rs.getInt("money"));
return member;
}
위 코드는 멤버를 조회하는 로직이다.
pstmt.executeQuery()
는 ResultSet을 반환하는데 rs는 rs.next()를 한번 수행해야 데이터를 꺼내올 수 있다.