KEMBAR78
Refactoring Jdbc Programming | PPT
Refactoring JDBC programming 2008.10.12 박찬욱
Hand-made JdbcTemplate 1.1  문제 인식 공유 1.2  해결 방안 모색 1.3 Refactoring with Strategy pattern Spring JdbcTemplate 2.1 Best Practice of JDBC Strategy 2.2 Simplify JDBC operation Table of Contents
오늘의 목표는 ? Composition + interface-based  프로그래밍 기법 Spring JdbcTemplate  이해하기 어디 쓸 만한 곳이 없을까 ?
1.  Hand-made JdbcTemplate
1.1  문제 인식 공유 퀴즈 iBatis ORM(Hibernate or TopLink  등 ) 내부 추상화 프레임웍 쌩 (pure) JDBC~?
1.1  문제 인식 공유 JDBC  근본적인 문제 TCFTC T ry- C atch- F inally- T ry- C atch 최고의  boilerplate  코드 Connection / Resource  누수 문제 SQLException 데이터베이스 벤더 별로 정의된  error code, error state  정보 Connection con = null;  Statement stmt = null;  try {  con = dataSource.getConnection();  stmt = con.createStatement();  stmt.executeUpdate(“UPDATE TABLE_NAME SET...”);  }c atch(SQLException e){ // 예외 처리 ... }finally {  if (stmt != null) { try { stmt.close(); }  catch (SQLException ex) {} }  if (con != null) try { con.close(); } catch (SQLException ex) { }  }
1.1  문제 인식 공유 전혀  OO  스럽지 않은 반복적인 코드 (boilerplate code) 의 사용으로  Data Access  코드가 드러워져 간다 “ Bad Java code is bad J2EE code.” - Rod Johnson
1.2  해결 방안 모색 Strategy pattern 을  도입해서  문제 해결  시도
1.2  해결 방안 모색 Strategy pattern  이란 ? 실행 시점에 (at runtime)  알고리즘을 선택할 수 있는 방법
1.2  해결 방안 모색 왜  Strategy pattern 을 택했나 ? Programming to  Interface  instead of Concrete Class (Achieving Loose Coupling with Interface) - Favor object  composition  over class inheritance  (Prefer Object Composition to Concrete Inheritance)
2.1 Best Practice of JDBC Strategy Strategy pattern 참조 : wiki[2]
1.3 Refactoring with Strategy pattern 변경되는 부분과 그렇지 않은 부분 식별하기 ,  각각 Updating sql  실행 try  { // get DB connection con =  getConnection(); // create Statement stmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); }  catch  (SQLException exception) { //  예외처리 }  finally  { if  (stmt !=  null ) { try  { stmt.close();} catch (SQLException e){} } // end if if  (con !=  null ) { try  { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return  result; try  { // get DB connection con =  getConnection(); // create Statement stmt = con.prepareStatement( "insert into LECTURE values(?, ?, ?, ?, ?)“ ); // binding sql parameters stmt.setInt(1,  incrementer .nextIntValue()); // ... // execute Query result = stmt.executeUpdate(); }  catch  (SQLException exception) { //  예외처리 }  finally  { if  (stmt !=  null ) { try  { stmt.close();} catch (SQLException e){} } // end if if  (con !=  null ) { try  { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return  result; update() insert()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement stmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); }  catch  (SQLException exception) { //  예외처리 }  finally  { if  (stmt !=  null ) { try  { stmt.close();} catch (SQLException e){} } // end if if  (con !=  null ) { try  { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return  result; 메소드 인자로 빼냄 콜백 메소드로 구현 공통 메소드로 추출 update() insert()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement stmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); }  catch  (SQLException exception) { //  예외처리 }  finally  { if  (stmt !=  null ) { try  { stmt.close();} catch (SQLException e){} } // end if if  (con !=  null ) { try  { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return  result; update() insert()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement stmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); }  catch  (SQLException exception) { //  예외처리 }  finally  { if  (stmt !=  null ) { try  { stmt.close();} catch (SQLException e){} } // end if if  (con !=  null ) { try  { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return  result; update()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement stmt = con.prepareStatement( " insert into LECTURE values(?, ?, ?, ?, ?)“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); }  catch  (SQLException exception) { //  예외처리 }  finally  { if  (stmt !=  null ) { try  { stmt.close();} catch (SQLException e){} } // end if if  (con !=  null ) { try  { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return  result; insert()
1.3 Refactoring with Strategy pattern Strategy pattern 이 적용된  Template.update()
1.3 Refactoring with Strategy pattern 변경되는 부분과 그렇지 않은 부분 식별하기 ,  각각 querying sql  실행 try  { // get DB connection con =  getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while  (rs.next()) { result =  new  Lecture(); Result.setName(rs.getString(2)); // extracting... } }  catch  (SQLException exception) { //  예외처리 }  finally  { //  자원 반환 처리 } return  result; try  { // get DB connection con =  getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE“ ); // binding sql parameter // execute Query rs = stmt.executeQuery(); //extract result while  (rs.next()) { lecture =  new  Lecture(); Result.setName(rs.getString(2)); // extracting... result.add(lecture); } }  catch  (SQLException exception) { //  예외처리 }  finally  { //  자원 반환 처리 } return  result; get() getall()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while  (rs.next()) { result =  new  Lecture(); Result.setName(rs.getString(2)); // extracting... } }  catch  (SQLException exception) { //  예외처리 }  finally  { //  자원 반환 처리 } return  result; get() 메소드 인자로 빼냄 콜백 메소드로 구현 공통 메소드로 추출 getall()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while  (rs.next()) { result =  new  Lecture(); Result.setName(rs.getString(2)); // extracting... } }  catch  (SQLException exception) { //  예외처리 }  finally  { //  자원 반환 처리 } return  result; get() getall()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while  (rs.next()) { result =  new  Lecture(); Result.setName(rs.getString(2)); // extracting... } }  catch  (SQLException exception) { //  예외처리 }  finally  { //  자원 반환 처리 } return  result; getall()
1.3 Refactoring with Strategy pattern try  { // get DB connection con =  getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while  (rs.next()) { result =  new  Lecture(); Result.setName(rs.getString(2)); // extracting... } }  catch  (SQLException exception) { //  예외처리 }  finally  { //  자원 반환 처리 } return  result; get()
1.3 Refactoring with Strategy pattern Strategy pattern 이 적용된  Template.query()
1.3 Refactoring with Strategy pattern Refactoring 1. 결과 값의 타입은 ? ResultSet  처리 동일한  DTO 인 경우 ,  거의 동일하게  ResultSet 에서 값을 빼내는 코드가 반복됨 return  (Lecture)  template .query( &quot;select * from LECTURE where ID=?&quot; , ... },  new  ResultSetExtractor() { public  Object extractResult(ResultSet rs) throws  SQLException { // extract result to Single Object Lecture result =  new  Lecture(); while  (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return  result; } }); return  (List<Lecture>)  template .query( &quot;select * from LECTURE&quot; , ... },  new  ResultSetExtractor() { public  Object extractResult(ResultSet rs) throws  SQLException { // extract result to Collection Object List<Lecture> result =  new  ArrayList<Lecture>(); while  (rs.next()) { Lecture lecture =  new  Lecture(); lecture.setId(rs.getInt(1)); lecture.setName(rs.getString(2)); lecture.setSpeaker(rs.getString(3));   result.add(lecture); } return  result; } }); get() getall()
1.3 Refactoring with Strategy pattern return  (Lecture)  template .query( &quot;select * from LECTURE where ID=?&quot; , ... },  new  ResultSetExtractor() { public  Object extractResult(ResultSet rs) throws  SQLException { // extract result to Single Object Lecture result =  new  Lecture(); while  (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return  result; } }); get() 콜백 메소드로 구현 API 로 구분
1.3 Refactoring with Strategy pattern return  (Lecture)  template .query( &quot;select * from LECTURE where ID=?&quot; , ... },  new  ResultSetExtractor() { public  Object extractResult(ResultSet rs) throws  SQLException { // extract result to Single Object Lecture result =  new  Lecture(); while  (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return  result; } }); get()
1.3 Refactoring with Strategy pattern return  (Lecture)  template .query( &quot;select * from LECTURE where ID=?&quot; , ... },  new  ResultSetExtractor() { public  Object extractResult(ResultSet rs) throws  SQLException { // extract result to Single Object Lecture result =  new  Lecture(); while  (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return  result; } }); get()
1.3 Refactoring with Strategy pattern Refactoring 2. 여전히  Template 의  query() 와  update() 에서  JDBC API 가 중복되어 사용된다 !
1.3 Refactoring with Strategy pattern Refactoring 2.  결과
1.3 Refactoring with Strategy pattern 콜백 인터페이스가 적용된 공통 메소드
1.4 Summary 구현한 템플릿 클래스와 인터페이스
1.4 Summary JdbcTemplate  도입된 이후의 효과 JDBC workflow 의 흐름 진행 주체 DAO    JdbcTemplate DAO 의 역할 충실화 SQL,  파라미터 제공  or  결과 매핑 이 외의 다른 역할은  JdbcTemplate 를 비롯한 각 담당자에게 위임
2. SPRING JDBCTEMPLATE
2.1 Best Practice of JDBC Strategy Spring JDBC core package’s Central class Jdbc UseCase Best Practice Collaborate with Various Callback Interface    Strategy pattern ! Convenience DA operation &quot;This is  a special case of the Strategy design pattern .  It appears different because  the interface involved  are so simple &quot;
2.1 Best Practice of JDBC Strategy JdbcTemplate with Strategy pattern DAO Template Callback Interface implementation 참조 : wiki[2]
2.1 Best Practice of JDBC Strategy Jdbc-based DAO Spring-based DAO DriverManager / DataSource DataSource Statement / PreparedStatement / CallableStatement JdbcTemplate / Callback interface ResultSet  POJO / POJO’s collection
2.1 Best Practice of JDBC Strategy Task Spring You Connection(DataSource) management Provide SQL Statement management Parameter Declaration Provide parameter value ResultSet management Row Data Retrieval Transaction management Exception handling
2.1 Best Practice of JDBC Strategy Convenience , but  powerful  Jdbc Template Resource management DataSourceUtils Integrated with Transaction management Spring-tx (non-invasive)
2.1 Best Practice of JDBC Strategy Convenience , but  powerful  JdbcTemplate Consistent exception management 예외 발생 시 처리 기준 에러 코드 (error code),  에러 상태 (error state)    예외 종류 (type of Exception) Check exception    Unchecked exception SQLExceptionTranslator
2.1 Best Practice of JDBC Strategy Convenience , but  powerful  JdbcTemplate Logging for SQL inform. (DEBUG level) Various Template JdbcTemplate NamedParameterJdbcTemplate SimpleJdbcTemplate Convenience DA operation named parameter Auto-detect column by Jdbc Driver Easily using Batch, LOB
2.1 Best Practice of JDBC Strategy JdbcTemplate  구성 방법 DataSource(or Connection Pool) 가 쓰레드 안전하다면 , JdbcTemplate 도 쓰레드 안전 private  JdbcTemplate  template ; public   void  setTemplate(DataSource dataSource) { this . template  =  new  JdbcTemplate(dataSource); } < bean  id = &quot;lectureDao&quot;  class = &quot;org.springframework.lecture.jdbc.dao.JdbcLectureDao&quot; > < property  name = &quot;template&quot;  ref = &quot;dataSource&quot;  /> </ bean > private  JdbcTemplate  template ; public   void  setTemplate(JdbcTemplate template) { this . template  = template; } < bean  id = &quot;lectureDao&quot;  class = &quot;org.springframework.lecture.jdbc.dao.JdbcLectureDao&quot; > < property  name = &quot;template&quot;  ref = &quot;jdbcTemplate&quot;  /> </ bean >
2.2 SIMPLIFY JDBC OPERATION
2.2 Simplify JDBC operation SimpleJdbc*  활용하기 SimpleJdbcTemplate Wrapper around classic JdbcTemplate class(getJdbcOperations()) Java-5-based convenience wrapper for the classic Spring  JdbcTemplate Varargs, Generic, Autoboxing, Unboxing...
2.2 Simplify JDBC operation SimpleJdbc*  활용하기 SimpleJdbcInsert Simplify Insert behavior JdbcTemplate + DatabaseMetaData ‘ fluid’ interface style
2.2 Simplify JDBC operation SimpleJdbc*  활용하기 SimpleJdbcCall multi-threaded, reusable object representing a call to stored procedure or a stored function SimpleJdbcTestUtils
2.2 Simplify JDBC operation The  Pareto Principle  in action JdbcTemplate+callback interface by Reflection = 80 SqlQuery + inheritance by explicit parameter mapping =20
2.2 Simplify JDBC operation RowMapper(with ResultSetExtractor) per-row basis Stateless & reusable Ideal choice of row-mapping logic ResultSetExtractor per-resultSet basis Stateless & reusable, if not access stateful resource
2.2 Simplify JDBC operation SqlQuery by Inheritance Reusable, threadsafe class Encapsulate SQL MappingSqlQuery & UpdatableSqlQuery Using meaningful method name
2.2 Simplify JDBC operation RowCallbackHandler Stateful public void processRow(ResultSet rs) throws SQLException
2.2 Simplify JDBC operation DataFieldMaxValueIncrementer  활용하기 Sequence-based Oracle, PostgreSQL, DB2(plain, mainframe), HSQL, H2 Column-based MySQL, MS-SqlServer, Sybase, Hsql, Derby BeanProperty*  활용하기 (Parameterized)BeanPropertyRowMapper BeanPropertySqlParameterSource
Reference wiki[1]:  http://en.wikipedia.org/wiki/Image:Strategy_Pattern_Diagram_ZP.svg wiki[2]:  http://en.wikipedia.org/wiki/Image:Strategy_pattern_in_LePUS3.gif Tomas[1]: JDBC Development with the Spring Framework Spring reference Spring API J2EE Design and Development J2EE without EJB
감사합니다 .

Refactoring Jdbc Programming

  • 1.
    Refactoring JDBC programming2008.10.12 박찬욱
  • 2.
    Hand-made JdbcTemplate 1.1 문제 인식 공유 1.2 해결 방안 모색 1.3 Refactoring with Strategy pattern Spring JdbcTemplate 2.1 Best Practice of JDBC Strategy 2.2 Simplify JDBC operation Table of Contents
  • 3.
    오늘의 목표는 ?Composition + interface-based 프로그래밍 기법 Spring JdbcTemplate 이해하기 어디 쓸 만한 곳이 없을까 ?
  • 4.
    1. Hand-madeJdbcTemplate
  • 5.
    1.1 문제인식 공유 퀴즈 iBatis ORM(Hibernate or TopLink 등 ) 내부 추상화 프레임웍 쌩 (pure) JDBC~?
  • 6.
    1.1 문제인식 공유 JDBC 근본적인 문제 TCFTC T ry- C atch- F inally- T ry- C atch 최고의 boilerplate 코드 Connection / Resource 누수 문제 SQLException 데이터베이스 벤더 별로 정의된 error code, error state 정보 Connection con = null; Statement stmt = null; try { con = dataSource.getConnection(); stmt = con.createStatement(); stmt.executeUpdate(“UPDATE TABLE_NAME SET...”); }c atch(SQLException e){ // 예외 처리 ... }finally { if (stmt != null) { try { stmt.close(); } catch (SQLException ex) {} } if (con != null) try { con.close(); } catch (SQLException ex) { } }
  • 7.
    1.1 문제인식 공유 전혀 OO 스럽지 않은 반복적인 코드 (boilerplate code) 의 사용으로 Data Access 코드가 드러워져 간다 “ Bad Java code is bad J2EE code.” - Rod Johnson
  • 8.
    1.2 해결방안 모색 Strategy pattern 을 도입해서 문제 해결 시도
  • 9.
    1.2 해결방안 모색 Strategy pattern 이란 ? 실행 시점에 (at runtime) 알고리즘을 선택할 수 있는 방법
  • 10.
    1.2 해결방안 모색 왜 Strategy pattern 을 택했나 ? Programming to Interface instead of Concrete Class (Achieving Loose Coupling with Interface) - Favor object composition over class inheritance (Prefer Object Composition to Concrete Inheritance)
  • 11.
    2.1 Best Practiceof JDBC Strategy Strategy pattern 참조 : wiki[2]
  • 12.
    1.3 Refactoring withStrategy pattern 변경되는 부분과 그렇지 않은 부분 식별하기 , 각각 Updating sql 실행 try { // get DB connection con = getConnection(); // create Statement stmt = con.prepareStatement( &quot;update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); } catch (SQLException exception) { // 예외처리 } finally { if (stmt != null ) { try { stmt.close();} catch (SQLException e){} } // end if if (con != null ) { try { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return result; try { // get DB connection con = getConnection(); // create Statement stmt = con.prepareStatement( &quot;insert into LECTURE values(?, ?, ?, ?, ?)“ ); // binding sql parameters stmt.setInt(1, incrementer .nextIntValue()); // ... // execute Query result = stmt.executeUpdate(); } catch (SQLException exception) { // 예외처리 } finally { if (stmt != null ) { try { stmt.close();} catch (SQLException e){} } // end if if (con != null ) { try { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return result; update() insert()
  • 13.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement stmt = con.prepareStatement( &quot;update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); } catch (SQLException exception) { // 예외처리 } finally { if (stmt != null ) { try { stmt.close();} catch (SQLException e){} } // end if if (con != null ) { try { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return result; 메소드 인자로 빼냄 콜백 메소드로 구현 공통 메소드로 추출 update() insert()
  • 14.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement stmt = con.prepareStatement( &quot;update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); } catch (SQLException exception) { // 예외처리 } finally { if (stmt != null ) { try { stmt.close();} catch (SQLException e){} } // end if if (con != null ) { try { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return result; update() insert()
  • 15.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement stmt = con.prepareStatement( &quot;update LECTURE SET name=? where ID=?“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); } catch (SQLException exception) { // 예외처리 } finally { if (stmt != null ) { try { stmt.close();} catch (SQLException e){} } // end if if (con != null ) { try { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return result; update()
  • 16.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement stmt = con.prepareStatement( &quot; insert into LECTURE values(?, ?, ?, ?, ?)“ ); // binding sql parameter stmt.setString(1, name); //... // execute Query result = stmt.executeUpdate(); } catch (SQLException exception) { // 예외처리 } finally { if (stmt != null ) { try { stmt.close();} catch (SQLException e){} } // end if if (con != null ) { try { con.close();} catch (SQLException e){} } // end if } // end try-catch-finally return result; insert()
  • 17.
    1.3 Refactoring withStrategy pattern Strategy pattern 이 적용된 Template.update()
  • 18.
    1.3 Refactoring withStrategy pattern 변경되는 부분과 그렇지 않은 부분 식별하기 , 각각 querying sql 실행 try { // get DB connection con = getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while (rs.next()) { result = new Lecture(); Result.setName(rs.getString(2)); // extracting... } } catch (SQLException exception) { // 예외처리 } finally { // 자원 반환 처리 } return result; try { // get DB connection con = getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE“ ); // binding sql parameter // execute Query rs = stmt.executeQuery(); //extract result while (rs.next()) { lecture = new Lecture(); Result.setName(rs.getString(2)); // extracting... result.add(lecture); } } catch (SQLException exception) { // 예외처리 } finally { // 자원 반환 처리 } return result; get() getall()
  • 19.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while (rs.next()) { result = new Lecture(); Result.setName(rs.getString(2)); // extracting... } } catch (SQLException exception) { // 예외처리 } finally { // 자원 반환 처리 } return result; get() 메소드 인자로 빼냄 콜백 메소드로 구현 공통 메소드로 추출 getall()
  • 20.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while (rs.next()) { result = new Lecture(); Result.setName(rs.getString(2)); // extracting... } } catch (SQLException exception) { // 예외처리 } finally { // 자원 반환 처리 } return result; get() getall()
  • 21.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while (rs.next()) { result = new Lecture(); Result.setName(rs.getString(2)); // extracting... } } catch (SQLException exception) { // 예외처리 } finally { // 자원 반환 처리 } return result; getall()
  • 22.
    1.3 Refactoring withStrategy pattern try { // get DB connection con = getConnection(); // create Statement rs = con.prepareStatement( “ select * from LECTURE where ID=?“ ); // binding sql parameter stmt.setInt(1, id); // execute Query rs = stmt.executeQuery(); //extract result while (rs.next()) { result = new Lecture(); Result.setName(rs.getString(2)); // extracting... } } catch (SQLException exception) { // 예외처리 } finally { // 자원 반환 처리 } return result; get()
  • 23.
    1.3 Refactoring withStrategy pattern Strategy pattern 이 적용된 Template.query()
  • 24.
    1.3 Refactoring withStrategy pattern Refactoring 1. 결과 값의 타입은 ? ResultSet 처리 동일한 DTO 인 경우 , 거의 동일하게 ResultSet 에서 값을 빼내는 코드가 반복됨 return (Lecture) template .query( &quot;select * from LECTURE where ID=?&quot; , ... }, new ResultSetExtractor() { public Object extractResult(ResultSet rs) throws SQLException { // extract result to Single Object Lecture result = new Lecture(); while (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return result; } }); return (List<Lecture>) template .query( &quot;select * from LECTURE&quot; , ... }, new ResultSetExtractor() { public Object extractResult(ResultSet rs) throws SQLException { // extract result to Collection Object List<Lecture> result = new ArrayList<Lecture>(); while (rs.next()) { Lecture lecture = new Lecture(); lecture.setId(rs.getInt(1)); lecture.setName(rs.getString(2)); lecture.setSpeaker(rs.getString(3)); result.add(lecture); } return result; } }); get() getall()
  • 25.
    1.3 Refactoring withStrategy pattern return (Lecture) template .query( &quot;select * from LECTURE where ID=?&quot; , ... }, new ResultSetExtractor() { public Object extractResult(ResultSet rs) throws SQLException { // extract result to Single Object Lecture result = new Lecture(); while (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return result; } }); get() 콜백 메소드로 구현 API 로 구분
  • 26.
    1.3 Refactoring withStrategy pattern return (Lecture) template .query( &quot;select * from LECTURE where ID=?&quot; , ... }, new ResultSetExtractor() { public Object extractResult(ResultSet rs) throws SQLException { // extract result to Single Object Lecture result = new Lecture(); while (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return result; } }); get()
  • 27.
    1.3 Refactoring withStrategy pattern return (Lecture) template .query( &quot;select * from LECTURE where ID=?&quot; , ... }, new ResultSetExtractor() { public Object extractResult(ResultSet rs) throws SQLException { // extract result to Single Object Lecture result = new Lecture(); while (rs.next()) { result.setId(rs.getInt(1)); result.setName(rs.getString(2)); result.setSpeaker(rs.getString(3)); } return result; } }); get()
  • 28.
    1.3 Refactoring withStrategy pattern Refactoring 2. 여전히 Template 의 query() 와 update() 에서 JDBC API 가 중복되어 사용된다 !
  • 29.
    1.3 Refactoring withStrategy pattern Refactoring 2. 결과
  • 30.
    1.3 Refactoring withStrategy pattern 콜백 인터페이스가 적용된 공통 메소드
  • 31.
    1.4 Summary 구현한템플릿 클래스와 인터페이스
  • 32.
    1.4 Summary JdbcTemplate 도입된 이후의 효과 JDBC workflow 의 흐름 진행 주체 DAO  JdbcTemplate DAO 의 역할 충실화 SQL, 파라미터 제공 or 결과 매핑 이 외의 다른 역할은 JdbcTemplate 를 비롯한 각 담당자에게 위임
  • 33.
  • 34.
    2.1 Best Practiceof JDBC Strategy Spring JDBC core package’s Central class Jdbc UseCase Best Practice Collaborate with Various Callback Interface  Strategy pattern ! Convenience DA operation &quot;This is a special case of the Strategy design pattern . It appears different because the interface involved are so simple &quot;
  • 35.
    2.1 Best Practiceof JDBC Strategy JdbcTemplate with Strategy pattern DAO Template Callback Interface implementation 참조 : wiki[2]
  • 36.
    2.1 Best Practiceof JDBC Strategy Jdbc-based DAO Spring-based DAO DriverManager / DataSource DataSource Statement / PreparedStatement / CallableStatement JdbcTemplate / Callback interface ResultSet POJO / POJO’s collection
  • 37.
    2.1 Best Practiceof JDBC Strategy Task Spring You Connection(DataSource) management Provide SQL Statement management Parameter Declaration Provide parameter value ResultSet management Row Data Retrieval Transaction management Exception handling
  • 38.
    2.1 Best Practiceof JDBC Strategy Convenience , but powerful Jdbc Template Resource management DataSourceUtils Integrated with Transaction management Spring-tx (non-invasive)
  • 39.
    2.1 Best Practiceof JDBC Strategy Convenience , but powerful JdbcTemplate Consistent exception management 예외 발생 시 처리 기준 에러 코드 (error code), 에러 상태 (error state)  예외 종류 (type of Exception) Check exception  Unchecked exception SQLExceptionTranslator
  • 40.
    2.1 Best Practiceof JDBC Strategy Convenience , but powerful JdbcTemplate Logging for SQL inform. (DEBUG level) Various Template JdbcTemplate NamedParameterJdbcTemplate SimpleJdbcTemplate Convenience DA operation named parameter Auto-detect column by Jdbc Driver Easily using Batch, LOB
  • 41.
    2.1 Best Practiceof JDBC Strategy JdbcTemplate 구성 방법 DataSource(or Connection Pool) 가 쓰레드 안전하다면 , JdbcTemplate 도 쓰레드 안전 private JdbcTemplate template ; public void setTemplate(DataSource dataSource) { this . template = new JdbcTemplate(dataSource); } < bean id = &quot;lectureDao&quot; class = &quot;org.springframework.lecture.jdbc.dao.JdbcLectureDao&quot; > < property name = &quot;template&quot; ref = &quot;dataSource&quot; /> </ bean > private JdbcTemplate template ; public void setTemplate(JdbcTemplate template) { this . template = template; } < bean id = &quot;lectureDao&quot; class = &quot;org.springframework.lecture.jdbc.dao.JdbcLectureDao&quot; > < property name = &quot;template&quot; ref = &quot;jdbcTemplate&quot; /> </ bean >
  • 42.
  • 43.
    2.2 Simplify JDBCoperation SimpleJdbc* 활용하기 SimpleJdbcTemplate Wrapper around classic JdbcTemplate class(getJdbcOperations()) Java-5-based convenience wrapper for the classic Spring JdbcTemplate Varargs, Generic, Autoboxing, Unboxing...
  • 44.
    2.2 Simplify JDBCoperation SimpleJdbc* 활용하기 SimpleJdbcInsert Simplify Insert behavior JdbcTemplate + DatabaseMetaData ‘ fluid’ interface style
  • 45.
    2.2 Simplify JDBCoperation SimpleJdbc* 활용하기 SimpleJdbcCall multi-threaded, reusable object representing a call to stored procedure or a stored function SimpleJdbcTestUtils
  • 46.
    2.2 Simplify JDBCoperation The Pareto Principle in action JdbcTemplate+callback interface by Reflection = 80 SqlQuery + inheritance by explicit parameter mapping =20
  • 47.
    2.2 Simplify JDBCoperation RowMapper(with ResultSetExtractor) per-row basis Stateless & reusable Ideal choice of row-mapping logic ResultSetExtractor per-resultSet basis Stateless & reusable, if not access stateful resource
  • 48.
    2.2 Simplify JDBCoperation SqlQuery by Inheritance Reusable, threadsafe class Encapsulate SQL MappingSqlQuery & UpdatableSqlQuery Using meaningful method name
  • 49.
    2.2 Simplify JDBCoperation RowCallbackHandler Stateful public void processRow(ResultSet rs) throws SQLException
  • 50.
    2.2 Simplify JDBCoperation DataFieldMaxValueIncrementer 활용하기 Sequence-based Oracle, PostgreSQL, DB2(plain, mainframe), HSQL, H2 Column-based MySQL, MS-SqlServer, Sybase, Hsql, Derby BeanProperty* 활용하기 (Parameterized)BeanPropertyRowMapper BeanPropertySqlParameterSource
  • 51.
    Reference wiki[1]: http://en.wikipedia.org/wiki/Image:Strategy_Pattern_Diagram_ZP.svg wiki[2]: http://en.wikipedia.org/wiki/Image:Strategy_pattern_in_LePUS3.gif Tomas[1]: JDBC Development with the Spring Framework Spring reference Spring API J2EE Design and Development J2EE without EJB
  • 52.