refactoring jdbc programming

52
한한 한한한 한한한 한한 (http://ksug.org) 1 Refactoring JDBC programming 2008.10.12 한한한

Upload: chanwook-park

Post on 25-Jan-2015

3.057 views

Category:

Technology


4 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 1

Refactoring JDBC programming

2008.10.12박찬욱

Page 2: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 2

1. Hand-made JdbcTemplate1.1 문제 인식 공유

1.2 해결 방안 모색

1.3 Refactoring with Strategy pattern

2. Spring JdbcTemplate2.1 Best Practice of JDBC Strategy

2.2 Simplify JDBC operation

Table of Contents

Page 3: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 3

오늘의 목표는 ?

•Composition + interface-based 프로그래밍 기법

Spring JdbcTemplate 이해하기

어디 쓸 만한 곳이 없을까 ?

Page 4: Refactoring Jdbc Programming

4 한국 스프링 사용자 모임 (http://ksug.org)

1. Hand-made JdbcTemplate

Page 5: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 5

1.1 문제 인식 공유• 퀴즈

– iBatis– ORM(Hibernate or TopLink 등 )– 내부 추상화 프레임웍– 쌩 (pure) JDBC~?

Page 6: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 6

1.1 문제 인식 공유• JDBC 근본적인 문제

– TCFTC• Try-Catch-Finally-Try-Catch• 최고의 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...”); }catch(SQLException e){ // 예외 처리 ...}finally { if (stmt != null) { try { stmt.close(); } catch (SQLException ex) {} } if (con != null) try { con.close(); } catch (SQLException ex) { } }

Page 7: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 7

1.1 문제 인식 공유• 전혀 OO 스럽지 않은 반복적인 코드 (boilerplate code) 의

사용으로 Data Access 코드가 드러워져 간다

“Bad Java code is bad J2EE code.”- Rod Johnson

Page 8: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 8

1.2 해결 방안 모색

Strategy pattern 을 도입해서 문제 해결 시도

Page 9: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 9

1.2 해결 방안 모색• Strategy pattern 이란 ?

– 실행 시점에 (at runtime) 알고리즘을 선택할 수 있는 방법

Page 10: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 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)

Page 11: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 11

2.1 Best Practice of JDBC Strategy• Strategy pattern

참조 : wiki[2]

Page 12: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 12

1.3 Refactoring with Strategy pattern• 변경되는 부분과 그렇지 않은 부분 식별하기 , 각각

– Updating sql 실행try {

// get DB connectioncon = getConnection();

// create Statementstmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“);

// binding sql parameterstmt.setString(1, name);//...

// execute Queryresult = stmt.executeUpdate();

} catch (SQLException exception) {// 예외처리

} finally {if (stmt != null) { try {stmt.close();}catch(SQLException e){}}// end ifif (con != null) { try {con.close();}catch(SQLException e){}}// end if

}// end try-catch-finallyreturn result;

try {// get DB connectioncon = getConnection();

// create Statementstmt = con.prepareStatement( "insert into LECTURE values(?, ?, ?, ?, ?)“);

// binding sql parametersstmt.setInt(1, incrementer.nextIntValue());// ...

// execute Queryresult = stmt.executeUpdate();

} catch (SQLException exception) {// 예외처리

} finally {if (stmt != null) { try {stmt.close();}catch(SQLException e){}}// end ifif (con != null) { try {con.close();}catch(SQLException e){}}// end if

}// end try-catch-finallyreturn result;

update() insert()

Page 13: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 13

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementstmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“);

// binding sql parameterstmt.setString(1, name);//...

// execute Queryresult = stmt.executeUpdate();

} catch (SQLException exception) {// 예외처리

} finally {if (stmt != null) { try {stmt.close();}catch(SQLException e){}}// end ifif (con != null) { try {con.close();}catch(SQLException e){}}// end if

}// end try-catch-finallyreturn result;

메소드 인자로 빼냄

콜백 메소드로 구현

공통 메소드로 추출

update()

insert()

Page 14: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 14

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementstmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“);

// binding sql parameterstmt.setString(1, name);//...

// execute Queryresult = stmt.executeUpdate();

} catch (SQLException exception) {// 예외처리

} finally {if (stmt != null) { try {stmt.close();}catch(SQLException e){}}// end ifif (con != null) { try {con.close();}catch(SQLException e){}}// end if

}// end try-catch-finallyreturn result;

update()

insert()

Page 15: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 15

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementstmt = con.prepareStatement( "update LECTURE SET name=? where ID=?“);

// binding sql parameterstmt.setString(1, name);//...

// execute Queryresult = stmt.executeUpdate();

} catch (SQLException exception) {// 예외처리

} finally {if (stmt != null) { try {stmt.close();}catch(SQLException e){}}// end ifif (con != null) { try {con.close();}catch(SQLException e){}}// end if

}// end try-catch-finallyreturn result;

update()

Page 16: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 16

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementstmt = con.prepareStatement( " insert into LECTURE values(?, ?, ?, ?, ?)“);

// binding sql parameterstmt.setString(1, name);//...

// execute Queryresult = stmt.executeUpdate();

} catch (SQLException exception) {// 예외처리

} finally {if (stmt != null) { try {stmt.close();}catch(SQLException e){}}// end ifif (con != null) { try {con.close();}catch(SQLException e){}}// end if

}// end try-catch-finallyreturn result;

insert()

Page 17: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 17

1.3 Refactoring with Strategy pattern• Strategy pattern 이 적용된 Template.update()

Page 18: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 18

1.3 Refactoring with Strategy pattern• 변경되는 부분과 그렇지 않은 부분 식별하기 , 각각

– querying sql 실행try {

// get DB connectioncon = getConnection();

// create Statementrs = con.prepareStatement( “select * from LECTURE where ID=?“);

// binding sql parameterstmt.setInt(1, id);

// execute Queryrs = stmt.executeQuery();

//extract resultwhile (rs.next()) {

result = new Lecture();Result.setName(rs.getString(2));// extracting...

}

} catch (SQLException exception) {// 예외처리

} finally {// 자원 반환 처리

}return result;

try {// get DB connectioncon = getConnection();

// create Statementrs = con.prepareStatement( “select * from LECTURE“);

// binding sql parameter

// execute Queryrs = stmt.executeQuery();

//extract resultwhile (rs.next()) {

lecture = new Lecture();Result.setName(rs.getString(2));// extracting...

result.add(lecture);}

} catch (SQLException exception) {// 예외처리

} finally {// 자원 반환 처리

}return result;

get() getall()

Page 19: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 19

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementrs = con.prepareStatement( “select * from LECTURE where ID=?“);

// binding sql parameterstmt.setInt(1, id);

// execute Queryrs = stmt.executeQuery();

//extract resultwhile (rs.next()) {

result = new Lecture();Result.setName(rs.getString(2));// extracting...

}

} catch (SQLException exception) {// 예외처리

} finally {// 자원 반환 처리

}return result;

get()

메소드 인자로 빼냄

콜백 메소드로 구현

공통 메소드로 추출

getall()

Page 20: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 20

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementrs = con.prepareStatement( “select * from LECTURE where ID=?“);

// binding sql parameterstmt.setInt(1, id);

// execute Queryrs = stmt.executeQuery();

//extract resultwhile (rs.next()) {

result = new Lecture();Result.setName(rs.getString(2));// extracting...

}

} catch (SQLException exception) {// 예외처리

} finally {// 자원 반환 처리

}return result;

get()getall()

Page 21: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 21

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementrs = con.prepareStatement( “select * from LECTURE where ID=?“);

// binding sql parameterstmt.setInt(1, id);

// execute Queryrs = stmt.executeQuery();

//extract resultwhile (rs.next()) {

result = new Lecture();Result.setName(rs.getString(2));// extracting...

}

} catch (SQLException exception) {// 예외처리

} finally {// 자원 반환 처리

}return result;

getall()

Page 22: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 22

1.3 Refactoring with Strategy pattern

try {// get DB connectioncon = getConnection();

// create Statementrs = con.prepareStatement( “select * from LECTURE where ID=?“);

// binding sql parameterstmt.setInt(1, id);

// execute Queryrs = stmt.executeQuery();

//extract resultwhile (rs.next()) {

result = new Lecture();Result.setName(rs.getString(2));// extracting...

}

} catch (SQLException exception) {// 예외처리

} finally {// 자원 반환 처리

}return result;

get()

Page 23: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 23

1.3 Refactoring with Strategy pattern• Strategy pattern 이 적용된 Template.query()

Page 24: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 24

1.3 Refactoring with Strategy pattern• Refactoring 1.

– 결과 값의 타입은 ?– ResultSet 처리

• 동일한 DTO 인 경우 , 거의 동일하게 ResultSet 에서 값을 빼내는 코드가 반복됨

return (Lecture) template.query("select * from LECTURE where ID=?",...}, new ResultSetExtractor() {

public Object extractResult(ResultSet rs)throws SQLException {

// extract result to Single ObjectLecture 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("select * from LECTURE",...}, new ResultSetExtractor() {

public Object extractResult(ResultSet rs)throws SQLException {

// extract result to Collection ObjectList<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()

Page 25: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 25

1.3 Refactoring with Strategy pattern

return (Lecture) template.query("select * from LECTURE where ID=?",...}, new ResultSetExtractor() {

public Object extractResult(ResultSet rs)throws SQLException {

// extract result to Single ObjectLecture 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 로 구분

Page 26: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 26

1.3 Refactoring with Strategy pattern

return (Lecture) template.query("select * from LECTURE where ID=?",...}, new ResultSetExtractor() {

public Object extractResult(ResultSet rs)throws SQLException {

// extract result to Single ObjectLecture result = new Lecture();

while (rs.next()) {result.setId(rs.getInt(1));result.setName(rs.getString(2));result.setSpeaker(rs.getString(3));

}

return result;

}});

get()

Page 27: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 27

1.3 Refactoring with Strategy pattern

return (Lecture) template.query("select * from LECTURE where ID=?",...}, new ResultSetExtractor() {

public Object extractResult(ResultSet rs)throws SQLException {

// extract result to Single ObjectLecture result = new Lecture();

while (rs.next()) {result.setId(rs.getInt(1));result.setName(rs.getString(2));result.setSpeaker(rs.getString(3));

}

return result;

}});

get()

Page 28: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 28

1.3 Refactoring with Strategy pattern• Refactoring 2.

– 여전히 Template 의 query() 와 update() 에서 JDBC API가 중복되어 사용된다 !

Page 29: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 29

1.3 Refactoring with Strategy pattern• Refactoring 2. 결과

Page 30: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 30

1.3 Refactoring with Strategy pattern• 콜백 인터페이스가 적용된 공통 메소드

Page 31: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 31

1.4 Summary• 구현한 템플릿 클래스와 인터페이스

Page 32: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 32

1.4 Summary• JdbcTemplate 도입된 이후의 효과

– JDBC workflow 의 흐름 진행 주체• DAO JdbcTemplate

– DAO 의 역할 충실화• SQL, 파라미터 제공 or 결과 매핑• 이 외의 다른 역할은 JdbcTemplate 를 비롯한 각 담당자에게 위임

Page 33: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 33

2. SPRING JDBCTEMPLATE

Page 34: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 34

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

"This is a special case of the Strategy design pattern. It appears different because the interface involved are so simple"

Page 35: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 35

2.1 Best Practice of JDBC Strategy• JdbcTemplate with Strategy pattern

DAO

Template

CallbackInterface

implementation참조 : wiki[2]

Page 36: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 36

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

Page 37: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 37

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

Page 38: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 38

2.1 Best Practice of JDBC Strategy• Convenience, but powerful Jdbc Template

– Resource management• DataSourceUtils

– Integrated with Transaction management• Spring-tx (non-invasive)

Page 39: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 39

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

Page 40: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 40

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

Page 41: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 41

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="lectureDao" class="org.springframework.lecture.jdbc.dao.JdbcLectureDao">

<property name="template" ref="dataSource" /></bean>

private JdbcTemplate template;

public void setTemplate(JdbcTemplate template) {this.template = template;

}

<bean id="lectureDao" class="org.springframework.lecture.jdbc.dao.JdbcLectureDao">

<property name="template" ref="jdbcTemplate" /></bean>

Page 42: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 42

2.2 SIMPLIFY JDBC OPERATION

Page 43: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 43

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...

Page 44: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 44

2.2 Simplify JDBC operation• SimpleJdbc* 활용하기

– SimpleJdbcInsert• Simplify Insert behavior• JdbcTemplate + DatabaseMetaData• ‘fluid’ interface style

Page 45: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 45

2.2 Simplify JDBC operation• SimpleJdbc* 활용하기

– SimpleJdbcCall• multi-threaded, reusable object representing a call to stored

procedure or a stored function

– SimpleJdbcTestUtils

Page 46: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 46

2.2 Simplify JDBC operation• The Pareto Principle in action

– JdbcTemplate+callback interface by Reflection = 80– SqlQuery + inheritance by explicit parameter

mapping =20

Page 47: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 47

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

Page 48: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 48

2.2 Simplify JDBC operation• SqlQuery

– by Inheritance– Reusable, threadsafe class– Encapsulate SQL– MappingSqlQuery & UpdatableSqlQuery– Using meaningful method name

Page 49: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 49

2.2 Simplify JDBC operation• RowCallbackHandler

– Stateful– public void processRow(ResultSet rs) throws

SQLException

Page 50: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 50

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

Page 51: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 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

Page 52: Refactoring Jdbc Programming

한국 스프링 사용자 모임 (http://ksug.org) 52

감사합니다 .