기존의 JDBC 코드들은 드라이버 로딩, 커넥션 연결, SQL문 전송, 결과 받기 등 일련의 반복된 과정을 수행하도록 구성되어 있습니다. 이런 코드들을 대신해서 처리해주고 관리해주는 것이 바로 Spring JDBC입니다.
JdbcTemplate 클래스
JdbcTemplate은 GoF 디자인 패턴 중 템플릿 메서드 패턴이 적용된 클래스 입니다.
템플릿 메서드 패턴은 복잡하고 반복되는 알고리즘을 캡슐화해서 재사용하는 패턴으로 정의할 수 있습니다. (JDBC 코딩처럼 순서가 정형화된 기술에서 유용하게 사용 가능 합니다.)
Spring JDBC 설정
1. 라이브러리 추가
- Spring JDBC와 DBCP API 의존성 추가 : mvnrepository.com 에서 spring-jdbc, commons-dbcp2
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
<!-- spring version 으로 맞춰줬습니다. 5.3.16 -->
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
2. DataSource 설정 (프로퍼티 파일을 활용)
src/main/resources 에 패키지 생성 해서 config 폴더를 생성한 후에 그 곳에 File 생성해서 프로퍼티 파일을 생성
- database.properties
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521/XEPDB1
jdbc.username=mytest
jdbc.password=mytest
- applicationContext.xml
<context:component-scan base-package="zinc.spring.web"></context:component-scan>
<!-- spring jdbc 설정 -->
<context:property-placeholder location="classpath:config/database.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
JdbcTemplate 메서드
1. update() 메서드 : insert, update, delete 구문 처리
2. queryForObject() 메서드 : select 구문의 실행 결과를 특정 자바 객체로 매핑하여 리턴받을 때 사용
-> 검색결과가 없거나 검색결과가 두 개 이상이면 예외 발생
-> 검색 결과를 자바객체로 매핑할 RowMapper 객체를 반드시 지정
3. query() 메서드 : queryForObject() 메서드가 select문으로 하나의 결과를 검색할 때 사용하는 메서드라면 query() 메서드는 select문의 실행 결과가 목록일 때 사용
RowMapper() : 검색 결과를 특정 VO 객체에 매핑하여 리턴하려면 RowMapper 인터페이스를 구현한 RowMapper 클래스가 반드시 필요합니다. 결국 RowMapper 클래스는 테이블 당 하나씩은 필요하다는 뜻입니다.
DAO 클래스 구현
1. JdbcTemplate 클래스 <bean> 등록 및 의존성 주입
- applicationContext.xml 추가
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
2. BoardDAOSpring 클래스 구현
- BoardDAOSpring.java
package zinc.spring.web.board.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import zinc.spring.web.board.BoardVO;
@Repository
public class BoardDAOSpring {
@Autowired // 의존성 주입
private JdbcTemplate jdbcTemplate;
private final String BOARD_INSERT = "insert into myboard(seq, title, writer, content) "
+ "values((select nvl(max(seq), 0)+1 from myboard), ?, ?, ?)";
private final String BOARD_UPDATE = "update myboard set title=?, content=? where seq=?";
private final String BOARD_DELETE = "delete myboard where seq=?";
private final String BOARD_GET = "select * from myboard where seq=?";
private final String BOARD_LIST = "select * from myboard order by seq desc";
public void insertBoard(BoardVO vo) {
System.out.println("Spring JDBC로 insertBoard() 기능 처리");
jdbcTemplate.update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
// try catch 안해도 spring이 해줌
}
public void updateBoard(BoardVO vo) {
System.out.println("Spring JDBC로 updateBoard() 기능 처리");
jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
}
public void deleteBoard(BoardVO vo) {
System.out.println("Spring JDBC로 deleteBoard() 기능 처리");
jdbcTemplate.update(BOARD_DELETE, vo.getSeq());
}
public BoardVO getBoard(BoardVO vo) {
System.out.println("Spring JDBC로 getBoard() 기능 처리");
Object[] args = {vo.getSeq()};
return jdbcTemplate.queryForObject(BOARD_GET, new BoardRowMapper(), args);
}
public List<BoardVO> getBoardList(BoardVO vo){
System.out.println("Spring JDBC로 getBoardList() 기능 처리");
return jdbcTemplate.query(BOARD_LIST, new BoardRowMapper());
}
}
위에 보이는 코드처럼 단순히 쿼리문과 인자들만 넣어주면 jdbc의 규칙적인 구문을 실행하지 않고도 코드 작성이 가능합니다. 사전에 저는 BoardDAO와 Service 클래스인 BoardServiceImple을 엮어주었는데 그것만 추가해서 더 수정해주면 됩니다.
3. BoardServiceImpl 클래스 수정
package zinc.spring.web.board.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import zinc.spring.web.board.BoardService;
import zinc.spring.web.board.BoardVO;
import zinc.spring.web.common.LogAdvice;
@Service("boardService")
public class BoardServiceImpl implements BoardService{
@Autowired
private BoardDAOSpring boardDAO;
// private BoardDAO boardDAO;
@Override
public void insertBoard(BoardVO vo) {
boardDAO.insertBoard(vo);
}
@Override
public void updateBoard(BoardVO vo) {
boardDAO.updateBoard(vo);
}
@Override
public void deleteBoard(BoardVO vo) {
boardDAO.deleteBoard(vo);
}
@Override
public BoardVO getBoard(BoardVO vo) {
return boardDAO.getBoard(vo);
}
@Override
public List<BoardVO> getBoardList(BoardVO vo) {
return boardDAO.getBoardList(vo);
}
}
위처럼 BoardDAOSpring으로 바꿔주면 정상적으로 실행됩니다.
4. Controller에서 실행
package zinc.spring.web.board;
import java.util.List;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class BoardServiceClient {
public static void main(String[] args) {
// 1. 스프링 컨테이너 구동
AbstractApplicationContext container =
new GenericXmlApplicationContext("applicationContext.xml");
// 2. 스프링 컨테이너로 부터 BoardServiceImpl 객체를 lookup 한다.
BoardService boardService = (BoardService)container.getBean("boardService");
// 3. 글 등록 기능 테스트
BoardVO vo = new BoardVO();
vo.setTitle("제목");
vo.setWriter("이아연");
vo.setContent("ㅠㅠ");
boardService.insertBoard(vo);
// 4. 글 검색 기능 테스트
List<BoardVO> boardList = boardService.getBoardList(vo);
for(BoardVO board : boardList) {
System.out.println("==> " + board.toString());
}
// 5. 스프링 컨테이너 종료
container.close();
}
}
위처럼 JdbcTemplate을 사용해도 정상적으로 작동하는 것을 확인할 수 있습니다.
'language > Spring' 카테고리의 다른 글
[Java/Spring] Spring 프로젝트 pom.xml에 적을 Postgresql maven (0) | 2022.03.27 |
---|---|
[Java/Spring] Spring Transaction / 스프링 트랜잭션 처리 (0) | 2022.03.23 |
[Java/Spring] JoinPoint와 바인드 변수 (0) | 2022.03.20 |
[Java/Spring] AOP Pointcut 표현식 (0) | 2022.03.20 |
[Java/Spring] 빈 객체 라이프 사이클 (0) | 2022.03.20 |