서블렛 + JDBC 연동시 코딩 고려사항 ⑥

일반입력 :2002/04/19 00:00

이원영

다음과 같은 프로그램 형식을 생각할 수 있다. Connection conn = null; Statement stmt = null; ResultSet rs = null; try{ conn = ......; //.......(1) stmt = conn.createStatement(); //.............(2) rs = stmt.executeQuery("select ....."); // .....(3) while(rs.next()){ ...... } } finally { try { rs.close(); //........(4) stmt.close(); //......(5) ......; //......(6) }catch(Exception e){} }위에서 잘못된 내용은 무엇일까?finally 절에서 rs, stmt, conn을 null check 없이 동일한 try{}catch 절로 실행하고 있다. 예를 들어 (1), (2)번을 거치면서 conn과 stmt 객체까지는 제대로 수행됐으나 (3)번 Query문장 수행중 SQLException이 발생할 수 있다. 그러면 finally 절에서 (4)번 rs.close()를 수행하려 한다. 하지만 executeQuery가 실패했기 때문에 rs의 reference는 null 이므로 rs.close()시에 NullPointerException이 발생한다. 결국 정작 반드시 수행돼야 할 (5)번, (6)번이 실행되지 않는다. 따라서 반드시(!) 다음과 같은 형식의 코딩돼야 한다. Connection conn = null; Statement stmt = null; ResultSet rs = null; try{ conn = ......; stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select ....."); while(rs.next()){ ...... } } catch(Exception e){ .... } finally { if ( rs != null ) try{rs.close();}catch(Exception e){} if ( stmt != null ) try{stmt.close();}catch(Exception e){} if ( conn != null ) ......; }앞서 언급했듯이 ResultSet은 Statement가 close될 때 자원이 같이 해제되므로 다음과 같이 해도 크게 문제되지 않는다. Connection conn = null; Statement stmt = null; try{ conn = ......; stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select ....."); while(rs.next()){ ...... } rs.close(); } catch(Exception e){ .... } finally { //if ( rs != null ) try{rs.close();}catch(Exception e){} if ( stmt != null ) try{stmt.close();}catch(Exception e){} if ( conn != null ) ......; }간혹 다음과 같은 코딩은 문제를 야기하지 않을 것이라고 생각하는 사람들도 있다. finally{ try{ if ( stmt != null ) stmt.close(); if ( conn != null ) conn.close(); }catch(Exception e){} }저명한 책에서조차 위와 같이 코딩돼 있는 경우가 종종 있다. 물론 큰 문제가 있는 것은 아지만 웹애플리케이션서버의 Connection Pool과 연계해 사용할 땐 문제가 될 수 있다. 만약 stmt.close()시에 Exception이 throw되면 어떻게 할 것인가? 아니 무슨 null 체크까지 했는데, 무슨 Exception이 발생하느냐고 반문할 수도 있지만, 오랜 시간이 걸리는 SQL JOB에 빠져 있다가 Connection Pool의 "Orphan Timeout"을 넘어섰기 때문에 자동으로 해당 Connection을 Pool에 돌려보내거나 marking처리를 해 둘 수 있습니다. 이 경우라면 stmt.close()시에 해당 웹어플리케이션서버에 특화된 Exception이 발생하게 된다. conn.close()를 타지 못하게 되는 사태가 벌어진다. 따라서 앞서 언급된 대로 하는 것이 좋다. @ 서블렛 + JDBC 연동시 코딩 고려사항 ①서블렛 + JDBC 연동시 코딩 고려사항 ②서블렛 + JDBC 연동시 코딩 고려사항 ③서블렛 + JDBC 연동시 코딩 고려사항 ④서블렛 + JDBC 연동시 코딩 고려사항 ⑤