๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring/Spring Quick Start

ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ์ด์šฉํ•œ Spring JDBC

JDBC๋ž€?

JDBC๋Š” ์ž๋ฐ” ๊ฐœ๋ฐœ์ž๋“ค์ด ๊ฐ€์žฅ ์˜ค๋žซ๋™์•ˆ ์‚ฌ์šฉํ•œ DB ์—ฐ๋™ ๊ธฐ์ˆ ์ด๋‹ค.

JDBC ํ”„๋กœ๊ทธ๋žจ์€ ๊ฐœ๋ฐœ์ž๊ฐ€ ์ž‘์„ฑํ•ด์•ผ ํ•  ์ฝ”๋“œ๊ฐ€ ๊ต‰์žฅํžˆ ๋งŽ๋‹ค.

์Šคํ”„๋ง์€ JDBC ๊ธฐ๋ฐ˜์˜ DB ์—ฐ๋™ ํ”„๋กœ๊ทธ๋žจ์„ ์‰ฝ๊ฒŒ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก JDBCTemplate ํด๋ž˜์Šค๋ฅผ ์ง€์›ํ•œ๋‹ค.

๋ฐ˜๋ณต๋˜๋Š” DB ์—ฐ๋™ ๋กœ์ง์€ JDBCTemplate ํด๋ž˜์Šค์˜ ํ…œํ”Œ๋ฆฟ ๋ฉ”์†Œ๋“œ๊ฐ€ ์ œ๊ณตํ•˜๊ณ , ๊ฐœ๋ฐœ์ž๋Š” ๋‹ฌ๋ผ์ง€๋Š” SQL ๊ตฌ๋ฌธ๊ณผ ์„ค์ •๊ฐ’๋งŒ ์‹ ๊ฒฝ์“ฐ๋ฉด ๋œ๋‹ค.


์Šคํ”„๋ง JDBC ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

1. pom.xml์—์„œ JDBC์™€ DBCP ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

		<!-- JDBC -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<!-- DBCP -->
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.4</version>
		</dependency>

โ€‹

2. ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ์ด์šฉํ•˜์—ฌ DataSource๋ฅผ ๋“ฑ๋กํ•œ๋‹ค.

JdbcTemplate ํด๋ž˜์Šค๊ฐ€ JDBC API๋ฅผ ์ด์šฉํ•˜์—ฌ DB ์—ฐ๋™์„ ์ฒ˜๋ฆฌํ•˜๋ ค๋ฉด DB๋กœ๋ถ€ํ„ฐ ์ปค๋„ฅ์…˜์„ ์–ป์–ด์•ผ ํ•œ๋‹ค.

์ด ๊ณผ์ •์€ JdbcTemplate ๊ฐ์ฒด๊ฐ€ ์‚ฌ์šฉํ•  DataSource๋ฅผ ๋นˆ์œผ๋กœ ๋“ฑ๋กํ•˜์—ฌ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€  ์ƒ์„ฑํ•˜๋„๋ก ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์ฐธ๊ณ ๋กœ, DataSource ์„ค์ •์€ ๋งค์šฐ ์ค‘์š”ํ•œ ์„ค์ •์ด๋‹ค. ํŠธ๋žœ์žญ์…˜ ์ฒ˜๋ฆฌ, Mybatis ์—ฐ๋™, JPA ์—ฐ๋™์—์„œ๋„ ์‚ฌ์šฉ๋œ๋‹ค.

 

DataSource ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋Š” ๋‹ค์–‘ํ•˜์ง€๋งŒ, ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” Apache์˜ BasicDataSource๋ฅผ ๋“ฑ๋กํ–ˆ๋‹ค.

๊ฐ์ฒด๊ฐ€ ์‚ญ์ œ๋˜๊ธฐ ์ „์— ์—ฐ๊ฒฐ์„ ํ•ด์ œํ•˜๊ณ ์ž close() ๋ฉ”์†Œ๋“œ๋ฅผ destroy ์†์„ฑ์„ ์ง€์ •ํ•œ๋‹ค.

ํ”„๋กœํผํ‹ฐ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด <context:property-placeholder>๋กœ ์œ„์น˜๋ฅผ ๋“ฑ๋กํ•ด์•ผ ํ•œ๋‹ค.

"${}"๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

[src/main/resources/config/database.properties]

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springquickstart?serverTimezone=Asia/Seoul&useSSL=false&allowPublicKeyRetrieval=true
jdbc.username=jueun
jdbc.password=jueun
[applicationContext.xml ์ค‘]

<!-- DataSource ์„ค์ • -->
<context:property-placeholder location="classpath:config/database.properties" />

<bean id="ds" class="org.apache.commons.dbcp.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() ๋ฉ”์†Œ๋“œ

์ฒซ๋ฒˆ์งธ ๋ฐฉ์‹

SQL๋ฌธ์˜ '?' ์ˆ˜ ๋งŒํผ ๊ฐ’์„ ๋‚˜์—ดํ•˜๋Š” ๋ฐฉ์‹

int update(String sql, Object args, Object args......)

๋‘๋ฒˆ์งธ ๋ฐฉ์‹

Object ๋ฐฐ์—ด ๊ฐ์ฒด์— SQL ๊ตฌ๋ฌธ์— ์„ค์ •๋œ '?' ์ˆ˜ ๋งŒํผ ๊ฐ’์„ ์„ธํŒ…ํ•ด ๋ฐฐ์—ด ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹

int update(String sql, Obejct[] args)

2. queryForInt() ๋ฉ”์†Œ๋“œ

select ๋ฌธ์œผ๋กœ ๊ฒ€์ƒ‰๋œ ๊ฐ’์ค‘์— ์ •์ˆ˜๋ฅผ ๋ฆฌํ„ด๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

int queryForInt(String sql) 
int queryForInt(String sql, Object args...) 
int queryForInt(String sql, Object[] args)

3. queryForObject() ๋ฉ”์†Œ๋“œ

select ๋ฌธ์œผ๋กœ ๊ฒ€์ƒ‰๋œ ๊ฒฐ๊ณผ์—์„œ ๊ฐ์ฒด๋กœ ๋ฆฌํ„ด๋ฐ›์„ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

Object queryForObject(String sql) 
Object queryForObject(String sql, RowMapper<t> rowMapper) 
Object queryForObject(String sql, Object[] args, RowMapper<t> rowMapper)

4. query() ๋ฉ”์†Œ๋“œ

select ๋ฌธ์œผ๋กœ ๊ฒ€์ƒ‰๋œ ๊ฒฐ๊ณผ์—์„œ ๋ฆฌ์ŠคํŠธ์ผ ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

List query(String sql) List query(String sql, RowMapper<t> rowMapper) 
List query(String sql, Object[] args, RowMapper<t> rowMapper)

โ€‹


DAO ํด๋ž˜์Šค ๊ตฌํ˜„ํ•ด๋ณด์ž!

DAO ํด๋ž˜์Šค์—์„œ JDBCTemplate ๊ฐ์ฒด๋ฅผ ์–ป๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€์ด๋‹ค.

1. ์ฒซ๋ฒˆ์งธ ๋ฐฉ๋ฒ•: JDBCDaoSupport ํด๋ž˜์Šค ์ƒ์†

package com.springbook.biz.board.impl;

import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

//DAO(Data Access Object)
@Repository
public class BoardDAOSpring extends JdbcDaoSupport {
	// 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";

	@Autowired
	public void setSuperDataSource(DataSource dataSource) {
		super.setDataSource(dataSource);
	}

	// CRUD ๊ธฐ๋Šฅ์˜ ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„
	// ๊ธ€ ๋“ฑ๋ก
	public void insertBoard(BoardVO vo) {
		System.out.println("===> Spring JDBC๋กœ insertBoard() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		getJdbcTemplate().update(BOARD_INSERT, vo.getTitle(), vo.getWriter(), vo.getContent());
	}

	// ๊ธ€ ์ˆ˜์ •
	public void updateBoard(BoardVO vo) {
		System.out.println("===> Spring JDBC๋กœ updateBoard() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		getJdbcTemplate().update(BOARD_UPDATE, vo.getTitle(), vo.getContent(), vo.getSeq());
	}

	// ๊ธ€ ์‚ญ์ œ
	public void deleteBoard(BoardVO vo) {
		System.out.println("===> Spring JDBC๋กœ deleteBoard() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		getJdbcTemplate().update(BOARD_DELETE, vo.getSeq());
	}

	// ๊ธ€ ์ƒ์„ธ ์กฐํšŒ
	public BoardVO getBoard(BoardVO vo) {
		System.out.println("===> Spring JDBC๋กœ getBoard() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		Object[] args = { vo.getSeq() };
		return getJdbcTemplate().queryForObject(BOARD_GET, args, new BoardRowMapper());
	}

	// ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("===> Spring JDBC๋กœ getBoardList() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		return getJdbcTemplate().query(BOARD_LIST, new BoardRowMapper());
	}
}

getJdbcTemplate() ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์†๋ฐ›์•„ ์‚ฌ์šฉํ•˜์—ฌ update(), query() ๋“ฑ ์›ํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

๋ฌธ์ œ๋Š” getJdbcTemplate() ๋ฉ”์†Œ๋“œ๊ฐ€ JdbcTemplate ๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋ ค๋ฉด DataSource ๊ฐ์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ํ•œ๋‹ค.

 

๊ทธ๋ž˜์„œ ๋ฐ”๋กœ @Autowired๋ฅผ ํ†ตํ•ด setDataSource() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ DataSource๋ฅผ ์˜์กด์„ฑ ์ฃผ์ž…ํ•œ๋‹ค.

๋ฉ”์†Œ๋“œ ์œ„์— @Autowired๋ฅผ ๋ถ™์ด๋ฉด ํ•ด๋‹น ๋ฉ”์†Œ๋“œ๋ฅผ ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ์ž๋™์œผ๋กœ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค.

์ด๋•Œ ๋ฉ”์†Œ๋“œ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์„ ํ™•์ธํ•˜๊ณ  ํ•ด๋‹น ํƒ€์ž…์˜ ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์กด์žฌํ•˜๋ฉด ๊ทธ ๊ฐ์ฒด๋ฅผ ์ธ์ž๋กœ ๋„˜๊ฒจ์ค€๋‹ค.

2. ๋‘๋ฒˆ์งธ ๋ฐฉ๋ฒ•: JDBCTemplate ํด๋ž˜์Šค <bean> ๋“ฑ๋ก, ์˜์กด์„ฑ ์ฃผ์ž…

์ผ๋ฐ˜์ ์œผ๋กœ ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•œ๋‹ค.

[applicationContext.xml์— ๋นˆ ๋“ฑ๋ก]

<!-- Spring JDBC ์„ค์ • -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource" />
	</bean>

๋ฐ‘์—์„œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„์€ JdbcTemplate ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ @Autowired ๋งŒ์œผ๋กœ ๋๋‚ธ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

package com.springbook.biz.board.impl;

import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Repository;

import com.springbook.biz.board.BoardVO;

//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_INSERT = "insert into board(seq, title, writer, content) values(?, ?, ?, ?)";
	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("===> Spring JDBC๋กœ insertBoard() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		jdbcTemplate.update(BOARD_INSERT, vo.getSeq(), vo.getTitle(), vo.getWriter(), vo.getContent());
	}

	// ๊ธ€ ์ˆ˜์ •
	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, args, new BoardRowMapper());
	}

	// ๊ธ€ ๋ชฉ๋ก ์กฐํšŒ
	public List<BoardVO> getBoardList(BoardVO vo) {
		System.out.println("===> Spring JDBC๋กœ getBoardList() ๊ธฐ๋Šฅ ์ฒ˜๋ฆฌ");
		return jdbcTemplate.query(BOARD_LIST, new BoardRowMapper());
	}
}