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

Refactoring Jdbc Programming

Jan 25, 2015

Download

Technology

chanwook Park

 
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
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

감사합니다 .