33
고고고고고고고고고 (ADVANCED JAVA PROGRAMMING) 고고고고고 고고고고고 2012 고 고고고고 고고고고 고고고 1

고급자바프로그래밍 (Advanced Java Programming)

Embed Size (px)

DESCRIPTION

고급자바프로그래밍 (Advanced Java Programming). 강원대학교 컴퓨터학부 2012 년 가을학기 담당교수 정충교. 3 장 템플릿. 변경이 거의 일어나지 않고 일정한 패턴을 유지하는 부분 응용에 따라 변경되는 부분. 예외처리를 제대로 하지 않으면 리소스 반환이 이루어지지 않아 서버 다운 위험 예외처림 예 리스트 3-2 리스트 3-3 반복적으로 나타나는 예외처리 문장들을 정리해야겠다. 3.2.2 변하는 부분과 변하지 않는 부분 분리. - PowerPoint PPT Presentation

Citation preview

Page 1: 고급자바프로그래밍 (Advanced Java Programming)

1

고급자바프로그래밍(ADVANCED JAVA PROGRAMMING)

강원대학교 컴퓨터학부2012 년 가을학기담당교수 정충교

Page 2: 고급자바프로그래밍 (Advanced Java Programming)

2

3 장 템플릿• 변경이 거의 일어나지 않고 일정한 패턴을

유지하는 부분• 응용에 따라 변경되는 부분

Page 3: 고급자바프로그래밍 (Advanced Java Programming)

3

• 예외처리를 제대로 하지 않으면 리소스 반환이 이루어지지 않아 서버 다운 위험

• 예외처림 예• 리스트 3-2• 리스트 3-3

• 반복적으로 나타나는 예외처리 문장들을 정리해야겠다 .

Page 4: 고급자바프로그래밍 (Advanced Java Programming)

4

• 리스트 3-4 UserDao 의 deleteAll 메소드

• 리스트 3-6 변하는 부분만 별로의 메소드로 추출

• 템플릿 메소드 패턴 적용

• 리스트 3-6 의 UserDao 의 makeStatement 메소드를 추상 메소드로 설정 --> UserDao 도 추상클래스가 됨

• 리스트 3-7 UserDao 의 서브클래스

3.2.2 변하는 부분과 변하지 않는 부분 분리

Page 5: 고급자바프로그래밍 (Advanced Java Programming)

5

3.2.2 변하는 부분과 변하지 않는 부분 분리

템플릿 메소드 패턴을 적용한 결과

문제점• Dao 메소드마다 서브클래스를 만들어야 함• 유연성 부족 - 컴파일 시점에 이미 클래스간 관계가 고정됨

Page 6: 고급자바프로그래밍 (Advanced Java Programming)

6

3.2.2 변하는 부분과 변하지 않는 부분 분리

컨텍스트에서 하는 일 - 변하지 않는 일

전략패턴의 적용

Page 7: 고급자바프로그래밍 (Advanced Java Programming)

7

• StatementStategy 전략 인터페이스

• public interface StatementStrategy {• PreparedStatement makePreparedStatement(Connection c)

throws SQLException; • }

• 리스트 3-9 deleteAll 기능의 StatementStrategy 전략 클래스 DeleteAllStatement

• 리스트 3-10 deleteAll 기능의 컨텍스트

• 문제점 - 컨텍스트 내에 구체적인 전략클래스가 고정되어 있음

3.2.2 변하는 부분과 변하지 않는 부분 분리

Page 8: 고급자바프로그래밍 (Advanced Java Programming)

8

DI 적용을 위한 클라이언트 / 컨텍스트 분리

그림 3-3 클라이언트가 있는 전략패턴

리스트 3-11 컨텍스트 코드 (jdbcContextWithStatementStrategy)리스트 3-12 클라이언트 역할의 deleteAll 코드

Page 9: 고급자바프로그래밍 (Advanced Java Programming)

9

3.3.1 add 기능에 대해서도 동일한 패턴 적용

리스트 3-14 add 기능의 StatementStrategy 전략 클래스 AddStatement

리스트 3-15 클라이언트 역할의 add 코드

Page 10: 고급자바프로그래밍 (Advanced Java Programming)

10

3.3.2 전략과 클라이언트의 동거

DeleteAllStatement, AddStatement 클래스들을 로컬클래스 혹은 익명클래스로 변환하여 클라이언트 내부에 삽입

간결하다 .

리스트 3-16리스트 3-17리스트 3-18리스트 3-19리스트 3-20

--> spring30-3.3

Page 11: 고급자바프로그래밍 (Advanced Java Programming)

11

• 3.4.1 jdbcContext 의 분리• jdbcContextWithStatementStrategy 메소드를 별도의 클래스로 분리• --> 다른 Dao 에서도 사용 가능

• 리스트 3-21 별도로 분리된 JdbcContext 클래스• 리스트 3-22 클라이언트 기능만 남은 UserDao 클래스• 리스트 3-23 설정파일

• --> spring30-3.4

• UserDao 와 JdbcContext 는 서로 연관이 깊어 JdbcContext 가 다른 클래스로 대체될 가능성이 거의 없으므로 인터페이스를 통해 연결하지 않고 직접 연결함

• spring30-3.4 은 아래 두 방법 중 B 방법을 적용함A. JdbcContext 를 스프링 빈으로 등록하여 UserDao 에 DI 하는 방법B. JdbcContext 를 스프링 빈으로 등록하지 않고 UserDao 의 파라미터 setter 메소드 코드가 직접

JdbcContext 를 UserDao 에 DI 하는 방법 ( 리스트 3-24, 리스트 3-25)

3.4 컨텍스트와 DI

Page 12: 고급자바프로그래밍 (Advanced Java Programming)

12

• 3.5.1 템플릿 / 콜백의 동작원리

• 프로젝트 spring30-3.4 의 기본 구조• 전략패턴 활용

• 클라이언트는 복잡하지만 일정 패턴을 갖는 작업• 전략 인터페이스를 구현한 클래스들이 익명클래스 형태로 클라이언트에게

편입됨

3.5 템플릿과 콜백

Page 13: 고급자바프로그래밍 (Advanced Java Programming)

13

그림 3-7 템플릿 / 콜백 작업 흐름

Page 14: 고급자바프로그래밍 (Advanced Java Programming)

14

그림 3-8 UserDao, JdbcContext, StatementStrategy 에 적용된 템플릿 / 콜백 패턴

프로젝트 spring30-3.4 코드 참고

Page 15: 고급자바프로그래밍 (Advanced Java Programming)

15

• 3.5 에서 우리가 직접 만들어 사용한 템플릿• public class JdbcContext

• 스프링은 JdbcContext 와 유사한 그러나 더욱 강력한 클래스를 제공함 - JdbcTemplate

3.6 스프링의 JdbcTemplate

Page 16: 고급자바프로그래밍 (Advanced Java Programming)

16

• JdbcTemplate 은 update 메소드를 지원함• (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/)

• int update(PreparedStatementCreator psc) - A• int update(String sql) - B• int update(String sql, Object... args) - C

3.6 스프링의 JdbcTemplate

Page 17: 고급자바프로그래밍 (Advanced Java Programming)

17

• int update(PreparedStatementCreator psc) - A• int update(String sql) - B• int update(String sql, Object... args) - C

리스트 3-46 PreparedStatementCreator 콜백을 인자로 주면서 update 호출 - A

// UserDao 의 메소드public void deleteAll( ) {

this.jdbcTemplate.update(

new PreparedStatementCreator() {

public PreparedStatement createPreparedStatement(Connection con)

throws SQLException {

return con.prepareStatement("delete from users");

}

}

);

}

3.6 스프링의 JdbcTemplate

Page 18: 고급자바프로그래밍 (Advanced Java Programming)

18

• int update(PreparedStatementCreator psc) - A• int update(String sql) - B• int update(String sql, Object... args) - C

• 리스트 3-47 sql 스트링을 인자로 주면서 update 호출 - B• JdbcTemplate 이 스스로 (sql 스트링을 참고하여 ) 콜백을 만들어 자기 자신에게

등록함

• // UserDao 의 메소드• public void deleteAll( ) {• this.jdbcTemplate.update("delete from users");• }

3.6 스프링의 JdbcTemplate

Page 19: 고급자바프로그래밍 (Advanced Java Programming)

19

• add, deleteAll 의 경우 데이터베이스에 쓰기만 하면 되지만 getCount 는 데이터베이스 질의 결과를 정수로 받아와야 함

• JdbcTemplate 은 query 메소드를 지원함• (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/)

• <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse)

• JdbcTemplate 오브젝트에게 query 메소드를 호출할 때는 두 개의 인자를 준다 . • 하나는 PreparedStatementCreator, 다른 하나는 ResultSetExtractor 이다 . • 이 두 인자들이 바로 콜백 오브젝트들이다 .

3.6.2 getCount 메소드에 JdbcTemplate 적용하기

Page 20: 고급자바프로그래밍 (Advanced Java Programming)

20

• <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse)

• JdbcTemplate 의 query 메소드가 실행될 때 우선 PreparedStatementCreator 의 cre-atePreparedStatement 메소드가 호출 ( 콜백 ) 되고 이 호출 결과로 반환되는 Prepared-Statement 가 execute 된다 . PreparedStatement 를 execute 하면 그 결과로 ResultSet 이 반환된다 .

• query 메소드가 수행하는 두번째 작업은 ResultSetExtractor 에게 extractData 메소드를 호출 ( 콜백 ) 하는 것이다 . 이 메소드를 호출할 때 질의 결과로 얻은 ResultSet 을 인자로 준다 . 이 extractData 메소드가 반환하는 결과가 최종적으로 query 메소드의 반환값이 된다 .

3.6.2 getCount 메소드에 JdbcTemplate 적용하기

Page 21: 고급자바프로그래밍 (Advanced Java Programming)

21

• <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse)

• <T> 는 타입 파라미터이다 . T 위치에 타입 이름이 들어갈 수 있다 . T 자리에 int 가 들어가면 query 메소드는 아래와 같은 형식으로 쓰이게 된다 .

• Integer query(PreparedStatementCreator psc, ResultSetExtractor<Integer> rse)

• 즉 , Integer 를 반환하는 ResultSetExtractor 를 사용하면 최종 query 반환 타입도 Integer 가 된다 .

3.6.2 getCount 메소드에 JdbcTemplate 적용하기

Page 22: 고급자바프로그래밍 (Advanced Java Programming)

22

• <T> T query(PreparedStatementCreator psc, ResultSetExtractor<T> rse)

• PreparedStatementCreator 의 createPreparedStatement 메소드와 ResultSetEx-tractor 의 extractData 메소드가 각각 어떤 작용을 하게 할지는 익명클래스로 구현한다 .

• 리스트 3-49 JdbcTemplate 을 이용해 만든 getCount()

3.6.2 getCount 메소드에 JdbcTemplate 적용하기

Page 23: 고급자바프로그래밍 (Advanced Java Programming)

23

• org.springframework.jdbc.core• Interface PreparedStatementCreator

• PreparedStatement createPreparedStatement(Connection con)• Create a statement in this connection.

• org.springframework.jdbc.core• Interface ResultSetExtractor<T>

• T extractData(ResultSet rs)• Implementations must implement this method to process the entire Result-

Set.

3.6.2 getCount 메소드에 JdbcTemplate 적용하기

Page 24: 고급자바프로그래밍 (Advanced Java Programming)

24

• JdbcTemplate 는 아래 메소드를 제공한다 .• int queryForInt(String sql)

• Execute a query that results in an int value, given static SQL.

• 스스로 두 개의 콜백을 만들어 사용하고 최종 결과를 반환

• 리스트 3-50• public getCount() {• return this.jdbcTemplate.queryForInt("select count(*) from users");

Page 25: 고급자바프로그래밍 (Advanced Java Programming)

25

• add, deleteAll 의 경우 데이터베이스에 쓰기만 하면 되고 , getCount 는 데이터베이스 질의 결과를 정수로 받아오면 되지만 , get 메소드는 User 객체를 반환해야 함

• JdbcTemplate 은 queryForObject 메소드를 지원함• (http://static.springsource.org/spring/docs/3.0.x/javadoc-api/)

• <T> T queryForObject(String sql, Object[] args, RowMapper<T> rowMapper)• Query given SQL to create a prepared statement from SQL and a list of arguments to bind to the

query, mapping a single result row to a Java object via a RowMapper.

• org.springframework.jdbc.core• Interface RowMapper<T>

• T mapRow(ResultSet rs, int rowNum)• Implementations must implement this method to map each row of data in

the ResultSet.

3.6.2 get 메소드에 JdbcTemplate 적용하기

Page 26: 고급자바프로그래밍 (Advanced Java Programming)

26

public User get(String id) {

return this.jdbcTemplate.queryForObject("select * from users where id = ?",

new Object[] {id}, new RowMapper<User>() {

public User mapRow(ResultSet rs, int rowNum) throws SQLException {

User user = new User();

user.setId(rs.getString("id"));

user.setName(rs.getString("name"));

user.setPassword(rs.getString("password"));

return user;

}

});

}

리스트 3-51 queryForObject 와 RowMapper 를 적용한 get 메소드

Page 27: 고급자바프로그래밍 (Advanced Java Programming)

27

• UserDao 의 getAll 메소드는 List<User> 를 반환하도록 하면 좋을 것임

• 테스트 코드를 먼저 만든다 .• UserDaoTest 에 getAll 테스트 메소드를 구현 -- 리스트 3-52

• UserDao 의 getAll 메소드 구현 -- 리스트 3-53

• <T> List<T>• query(String sql, RowMapper<T> rowMapper)• Execute a query given static SQL, mapping each row to a Java object via a

RowMapper.

3.6.4 테이블에 있는 레코드를 모두 다 읽어오는 getAll 메소드를 UserDao 에 추가

Page 28: 고급자바프로그래밍 (Advanced Java Programming)

28

• 테스트 보완• 네거티브 테스트 !

• 프로젝트 spring30-3.6.4

• 데이터베이스 드라이버 사용 , 예외처리 , 안전한 리소스 반환 등은 템플릿이 처리함• UserDao 에는 User 정보를 저장하거나 가져오는 로직만 남음• 자유로운 DataSource 선택 (DI 를 통해 ) - xml 구성설정 파일을 통해 UserDao

빈에 주입

Page 29: 고급자바프로그래밍 (Advanced Java Programming)

29

• UserDao 에서는 더 이상 DataSource 를 사용하지 않으므로 UserDao 의 data-Source 프로퍼티를 없앰

• 중복제거

• 리스트 3-56 재사용 가능하도록 독립시킨 RowMapper

• 리스트 3-57 공유 userMapper 를 이용하도록 수정한 get, getAll 메소드

3.6.5 재사용 가능한 콜백의 분리

Page 30: 고급자바프로그래밍 (Advanced Java Programming)

getCount {

}

UerDao

guery { ........

rs = ps.execute();

}

JdbcTemplate

createPreparedStatement() { }

PreparedStatementCreator

extractData(rs) { }

ResultSetExtractor

생성

생성

query( , )

호출(callback) PreparedStatement 반환

호출 (callback)

결과값 반환

결과값 반환

클라이언트 템플릿콜백

Page 31: 고급자바프로그래밍 (Advanced Java Programming)

31

역할의 분리• UserDao

• SQL

• JdbcTemplate• JDBC API 사용• 예외처리• 리소스 반납• DB 연결 획득

Page 32: 고급자바프로그래밍 (Advanced Java Programming)

32

추가적 개선1. UserMapper 를 스프링빈으로

• XML 설정 파일의 UserMapper 프로퍼티로 아래 정보 기입• User 테이블의 필드 – User 프로퍼티 매핑

• --> User 테이블이 바뀔 때 xml 파일만 수정하면 됨

2. UserDao 에 나타나는 SQL 문장을 별도의 파일로 저장하고 이를 불러 사용

• --> User 테이블이 바뀔 때 별도의 파일 수정하면 됨

Page 33: 고급자바프로그래밍 (Advanced Java Programming)

33