티스토리 뷰

spring

day2 class06 스프링 JDBC

일상다반ㅅㅏ 2019. 1. 13. 17:52

1. JdbcTemplate 클래스

- DB 연동 시 connection, close 등에 필요한 자바 코드를 대신 처리해 준다.

- GoF 디자인 패턴 중 템플릿 메소드 패턴이 적용된 클래스이다.

>>> 템플릿 메소드 패턴은 복잡하고 반복되는 알고리즘을 캡슐화해서 재사용하는 패턴으로 정의 할 수 있다.

- 반복되는 DB 연동 로직은 JdbcTemplate 클래스의 템플릿 메소드가 제공하고 개발자는 달라지는 SQL 구문과 설정값만 신경 쓰면 된다.



2. 스프링 JDBC 설정

2-1. 라이브러리 추가

- DBCP, jdbc 관련 설정을 추가한다.

>>> 책에 jdbc 표시를 애매하게 해놔서 뒤에 import가 안돼서 삽질했다...

- 설정 추가 후 maven dependency에 dbcp, jdbc관련 라이브러리가 생성되는 것을 확인한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- porm.xml -->
 
<dependencies>
    <!-- H2 데이터베이스 -->
    <!-- 생략... -->
        
    <!--  DBCP -->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
    
    <!-- Spring -->
    <!-- 생략... -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>
 
    <!-- 생략... -->
 
cs


2-2. DataSource 설정

- 커넥션을 얻기 위한 설정을 한다.

- DataSource 설정은 스프링 JDBC만을 위한 설정은 아니다. 트랜잭션 처리, Mybatis 연동, JPA 연동에서도 사용되는 중요한 설정이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- applicationContext.xml -->
 
<!-- DataSource 설정 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="org.h2.Driver" />
    <property name="url" value="jdbc:h2:tcp://localhost/~/test" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>
    
<!-- Spring JDBC 설정 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"></property>
</bean>
cs



3. JdbcTemplate 메소드

3-1. update()

- INSERT, UPDATE, DELETE 구문을 처리하기 위해 사용한다.

- "?"에 값을 설정하는 방법은 두가지로 나뉜다.

1
2
3
4
5
6
7
8
9
10
11
12
// 1. "?" 수만큼 값들을 차례대로 나열
// ~~~
private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
int cnt = jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContet(), vo.getSeq());
// ~~~
 
// 2. "?" 수만큼의 값들을 세팅하여 배열 객체를 두 번째 인자로 전달
// ~~~
private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
Object[] args = {vo.getTitle(), vo.getContet(), vo.getSeq()};
int cnt = jdbcTemplate.update(BOARD_UPDATE, args);
// ~~~
cs


3-2. queryForInt()

- SELECT 구문으로 겁색된 정수값을 리턴 받는다.

- 매개변수의 의미는 update()와 동일하다.


3-3. queryForObject()

- SELECT 구문의 실행 결과를 특정 자바 객체로 매피하여 리턴 받는다.

- 검색 결과가 없거나 검색 결과가 두 개 이상이면 예외(IncorretResultSizeDataAccessException)를 발생시킨다.

- 검색 결과를 자바 객체로 매핑할 RowMapper 객체를 반드시 지정해야 한다.

- RowMapper 객체를 queryForObject() 메소드의 매개변수로 넘겨주면, 스프링 컨테이너는 SQL 구문을 수행한 후 자동으로 RowMapper 객체의 mapRow()메소드를 호출한다.


3-4. query()

- SELECT  구문의 실행 결과가 목록일 때 사용한다.

- 기본 사용법은 queryForObject()와 동일하다.

- 검색된 객체 여러 개가 List 컬렉션에 저장되어 리턴된다.



4. DAO 클래스 구현

- JdbcTemplate 클래스를 <bean>등록하고, 의존성 주입으로 처리한다.

- <bean> 등록은 위의 DataSource 설정을 참고한다.

- JdbcTemplate 메소드를 사용하여 DAO 클래스를 수정한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// DAO(Data Access Object
@Repository
public class BoardDAOSpring {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
 
    // SQL 명령어들
    private final String BOARD_INSERT = "insert into board(seq, title, writer, content) values((select nvl(max(seq), 0)+1 from board),?,?,?)";
    private final String BOARD_UPDATE = "update board set title=?, content=? where seq=?";
    private final String BOARD_DELETE = "delete board where seq=?";
    private final String BOARD_GET = "select * from board where seq=?";
    private final String BOARD_LIST = "select * from board order by seq desc";
    
    // CRUD 기능의 메소드 구현
    // 글 등록
    public void insertBoard(BoardVO vo) {
        System.out.println("===> JDBC로 insertBoard() 기능 처리");
        jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
    }
    
    // 글 수정
    public void updateBoard(BoardVO vo) {
        System.out.println("===> JDBC로 updateBoard() 기능 처리");
        jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
    }
    
    // 글 삭제
    public void deleteBoard(BoardVO vo) {
        System.out.println("===> JDBC로 deleteBoard() 기능 처리");
        jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
    }
    
    // 글 상세 조회
    public BoardVO getBoard(BoardVO vo) {
        System.out.println("===> JDBC로 getBoard() 기능 처리");
        Object[] args = {vo.getSeq()};
        return jdbcTemplate.queryForObject(BOARD_GET, args, new BoardRowMapper());
    }
    
    // 글 목록 조회
    public List<BoardVO> getBoardList(BoardVO vo) {
        System.out.println("===> JDBC로 getBoardList() 기능 처리");
        return jdbcTemplate.query(BOARD_LIST, new BoardRowMapper());
    }
    
    class BoardRowMapper implements RowMapper<BoardVO> {
        public BoardVO mapRow(ResultSet rs, int rowNum) throws SQLException {
            BoardVO board = new BoardVO();
            board.setSeq(rs.getInt("SEQ"));
            board.setTitle(rs.getString("TITLE"));
            board.setWriter(rs.getString("WRITER"));
            board.setContent(rs.getString("CONTENT"));
            board.setRegDate(rs.getDate("REGDATE"));
            board.setCnt(rs.getInt("CNT"));
            return board;
        }
    }
}
cs


1
2
3
4
5
6
7
8
@Service("boardService")
public class BoardServiceImpl implements BoardService {
 
    @Autowired
    private BoardDAOSpring boardDAO;
 
    // 
}
cs