스프링 MVC - Spring JDBC

600g (Kim Dong Geun)·2020년 8월 24일
1
post-thumbnail

본 글은 스프링 MVC에 대해 지식을 정리하고 나중에 헷갈릴 때 다시 보기 위한 글입니다 👀

본 게시글은 Spring MVC Quick Start를 참조하여 정리한 글입니다. 📖 👀

본 게시글은 Spring MVC Documentation를 참조하여 정리한 글입니다 📚 👀

JDBC란?

Java를 이용하여 데이터베이스에 접속, SQL질의문의 실행과 그 결과를 데이터로 핸들링하는 절차 및 규약

JDBC를 이용하면 데이터 베이스에 비종속적인 DB 연동 로직을 구현할 수 있다.

즉 MYSQL을 쓰다가 Postgre로 얼마든지 옮길 수 있다는 소리다. 이는, JDBC API가 여러 DB Driver를 호환할 수 있는 인터페이스를 제공해주기 때문이다.

Spring JDBC란?

JDBC의 장점과 단순성을 그대로 유지하면서도 기존 JDBC의 단점을 극복할 수 있게 해주고, 간결한 형태의 API 사용법을 제공하며, JDBC API에서 지원되지 않는 편리한 기능을 제공.

출처: https://smallgiant.tistory.com/13 [나에게 남기는 지식]

JdbcTemplate

JdbcTemplate는 GoF 디자인 패턴 중 템플릿 메소드 패턴이 적용된 클래스이다. 템플릿 메소드 패턴은 복잡하고 반복되는 알고리즘을 캡슐화해서 재사용하는 패턴으로 정의할 수 있다.
따라서 반복되는 알고리즘을 템플릿 메소드로 캡슐화할 수 있어서 JDBC처럼 코딩 순서가 정형화된 기술에 유용하게 사용됨

따라서 개발자들은 JdbcTemplate 클래스가 어떻게 JDBC API를 이용하는지 모르고DB에 대한 접근과 데이터 핸들링이 가능하다.

스프링 JDBC 설정

Dependency 추가

  • pom.xml
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc></artifactId>
</dependency>

<dependency>
  <groupId>commons-dbcp</groupId>
  <artifactId>commons-dbcp</artifactId>
  <version>1.4</version>
</dependency>

DataSource 설정

JdbcTemplate 클래스가 JDBC API를 이용하려 DB연동을 처리하려면 반드시 데이터베이스로부터 커넥션을 얻어야 한다. 따라서 JdbcTemplate 객체가 사용할 DataSource를 <bean> 에 등록하여 스프링 컨테이너가 생성하도록 해야한다.

DataSource 설정은 스프링 JDBC만을 위한 설정은 아니다, 이후에 트랜잭션 처리, JPA 연동에서도 DataSource가 사용된다.

  • applicationContext.xml
<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>

Property File을 활용한 DataSource 설정

PropertyPlaceholderConfigurer를 이용하면 외부의 프로퍼티 파일을 참조하여 DataSource를 설정할 수 있다.

  • database.properties
jdbc.driver=org.h2.Driver
jdbc.url=jdbc.h2:tcp://localhost/~/test
jdbc.username=sa
jdbc.password=

이제 Properties 파일에 설정된 프로퍼티들을 이용해서 DataSource를 설정하려면 다음과 같이 <context:property-placeholder> 엘리먼트를 사용하면된다.

  • applicationContext.xml
<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>

JdbcTemplate 메소드

스프링 JDBC를 위한 기본 설정이 마무리 됐으면 이제 JdbcTemplate 객체를 이용하여 DB연동을 처리할 수 있다.

Update() 메소드

Insert, Update, Delete 구문을 처리하려면 JdbcTemplate 클래스의 Update() 메소드를 사용한다. update() 메소드의 사용법은 ? 값을 설정하는 방식에 따라 크게 두 가지 형태가 있다.

  1. 첫 번째는 SQL 구문에 설정된 ? 수 만큼 값들을 차례대로 나열 하는 것이다.

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());
}
  1. 두 번째는 Object 배열 객체에 SQL 구문에 설정된 ? 수 만큼의 값들을 세팅하여 배열 객체를 두 번째 인자로 전달하는 방식

    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);
}

queryForInt() 메소드

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() 메소드

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는 다음과 같이 정의된다.

  • BoardRowMapper.java
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하여 객체에 어떤 값을 부여할 것인지 정의한다.

query메소드

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)

예제는 생략!

profile
수동적인 과신과 행운이 아닌, 능동적인 노력과 치열함

0개의 댓글