본 글은 스프링 MVC에 대해 지식을 정리하고 나중에 헷갈릴 때 다시 보기 위한 글입니다 👀
본 게시글은 Spring MVC Quick Start를 참조하여 정리한 글입니다. 📖 👀
본 게시글은 Spring MVC Documentation를 참조하여 정리한 글입니다 📚 👀
Java를 이용하여 데이터베이스에 접속, SQL질의문의 실행과 그 결과를 데이터로 핸들링하는 절차 및 규약
JDBC를 이용하면 데이터 베이스에 비종속적인 DB 연동 로직을 구현할 수 있다.
즉 MYSQL을 쓰다가 Postgre로 얼마든지 옮길 수 있다는 소리다. 이는, JDBC API가 여러 DB Driver를 호환할 수 있는 인터페이스를 제공해주기 때문이다.
JDBC의 장점과 단순성을 그대로 유지하면서도 기존 JDBC의 단점을 극복할 수 있게 해주고, 간결한 형태의 API 사용법을 제공하며, JDBC API에서 지원되지 않는 편리한 기능을 제공.
출처: https://smallgiant.tistory.com/13 [나에게 남기는 지식]
JdbcTemplate는 GoF 디자인 패턴 중 템플릿 메소드 패턴
이 적용된 클래스이다. 템플릿 메소드 패턴은 복잡하고 반복되는 알고리즘을 캡슐화해서 재사용하는 패턴
으로 정의할 수 있다.
따라서 반복되는 알고리즘을 템플릿 메소드로 캡슐화할 수 있어서 JDBC처럼 코딩 순서가 정형화된 기술
에 유용하게 사용됨
따라서 개발자들은 JdbcTemplate 클래스가 어떻게 JDBC API를 이용하는지 모르고
도 DB에 대한 접근과 데이터 핸들링
이 가능하다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc></artifactId>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
JdbcTemplate 클래스가 JDBC API를 이용하려 DB연동을 처리하려면 반드시 데이터베이스로부터 커넥션을 얻어야 한다. 따라서 JdbcTemplate 객체가 사용할 DataSource를 <bean> 에 등록하여 스프링 컨테이너가 생성하도록 해야한다.
DataSource 설정은 스프링 JDBC만을 위한 설정은 아니다, 이후에 트랜잭션 처리, JPA 연동에서도 DataSource가 사용된다.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driver" ClassName value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:tcp://localhost/~/test"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
PropertyPlaceholderConfigurer
를 이용하면 외부의 프로퍼티 파일을 참조하여 DataSource를 설정할 수 있다.
jdbc.driver=org.h2.Driver
jdbc.url=jdbc.h2:tcp://localhost/~/test
jdbc.username=sa
jdbc.password=
이제 Properties 파일에 설정된 프로퍼티들을 이용해서 DataSource를 설정하려면 다음과 같이 <context:property-placeholder>
엘리먼트를 사용하면된다.
<context:property-placeholder location="classpath:config/database.properties"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driver" ClassName value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
스프링 JDBC를 위한 기본 설정이 마무리 됐으면 이제 JdbcTemplate 객체를 이용하여 DB연동을 처리할 수 있다.
Insert, Update, Delete 구문을 처리하려면 JdbcTemplate 클래스의 Update() 메소드를 사용한다. update() 메소드의 사용법은 ?
값을 설정하는 방식에 따라 크게 두 가지 형태가 있다.
?
수 만큼 값들을 차례대로 나열 하는 것이다.int update(String sql, Object... args)
사용예:
public void updateBoard(BoardVO vo){
String BOARD_UPDATE="update board set title=?, content=? where seq=?";
int cnt = jdbcTemplate.update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
}
?
수 만큼의 값들을 세팅하여 배열 객체를 두 번째 인자로 전달하는 방식int update(String sql, Object[] args)
public void updateBoard(Board vo){
String BOARD_UPDATE="update board set title=?, content=? where seq=?";
Object[] args = {vo.getTitle(), vo.getContent(), vo.getSeq()};
int cnt = jdbcTemplate.update(BOARD_UPDATE,args);
}
SELECT 구문으로 검색된 정숫값을 리턴받으려면 queryForInt()
메소드를 사용한다.
메소드
int queryForInt(String sql);
int queryForInt(String sql,Object... args);
int queryForInt(String sql,Object[] args);
사용예
public int getBoardTotalCount(BoardVO vo){
String BOARD_TOT_COUNT = "select count(*) from board";
int count = jdbcTemplate.queryForInt(BOARD_TOT_COUNT);
return count;
}
queryForObject 메소드는 SELECT 구문의 실행 결과를 특정 자바 객체로 매핑하여 리턴받을 때 사용한다. queryForObject() 메소드는 검색결과가 없거나 검색결과가 두 개 이상이면 예외(IncorrectResultSizeDataAccessException)
을 발생시킨다.
또한, 자바 객체로 매핑할 RowMapper 객체를 반드시 지정해줘야한다.
메소드
Object queryForObject(String sql)
Object queryForObject(String sql, RowMapper<T> rowMapper)
Object queryForObject(String sql, Object[] args, RowMapper<T> rowMapper)
사용 예
public BoardVO getBoard(BoardVO vo){
String BOARD_GET= "select * from board where seq=?";
Object[] args = {vo.getSEq()};
return jdbcTemplate.queryForObject(BOARD_GET,args,new BoardRowMapper());
}
BoardRowMapper는 다음과 같이 정의된다.
public class BoardRowMapper implements RowMapper<BoardVO>{
@Override
public BoardVO mapRow(ResultSet rs,int rowNum) throws SQLExceptions{
BoardVO board = new BoardVO();
board.setSeq(rs.getInt("SEQ"));
board.setTitle(rs.getString("TITLE"));
...
return board;
}
}
RowMapper<매핑할 클래스>를 인터페이스로 상속받고 구현한다.
mapRow 함수를 반드시 Override하여 객체에 어떤 값을 부여할 것인지 정의한다.
queryForObject()
가 select문으로 객체 하나를 검색할 때 사용하는 메소드라면, query() 메소드는 SELECT문의 실행결과가 리스트
일때 사용한다. 기본 사용법은 queryForObject와 같고 List<T>
를 리턴객체로 받는다.
query() 역시, RowMapper<T>가 구현되어 있어야 한다.
메소드
List query(String sql)
List query(String sql,RowMapper<T> rowMapper)
List query(String sql,Object[] args, RowMapper<T> rowMapper)
예제는 생략!