Spring JDBC
JDBC를 이용해서 프로그래밍을 하게 되면 반복적인 코드가 많이 발생하는데, 이런 반복적인 코드는 개발자의 생산성을 떨어트리는 주된 원인이 됩니다. 이러한 문제를 해결하기 위해 등장한 것이 Spring JDBC입니다. JDBC의 모든 저수준 세부사항을 스프링 프레임워크가 처리해 주니 개발자는 아래 표와 같이 필요한 부분만 작성하면 됩니다.
동작 | 스프링 | 개발자 |
연결 파라미터 정의 | ○ | |
연결 오픈 | ○ | |
SQL문 지정 | ○ | |
파라미터 선언과 파라미터 값 제공 | ○ | |
statement준비와 실행 | ○ | |
결과를 반복하는 루프 설정 | ○ | |
각 이터레이션에 대한 작업 수행 | ○ | |
모든 예외처리 | ○ | |
트랜잭션 제어 | ○ | |
연결, statement, resultset close | ○ |
Spring JDBC 패키지
패키지명 | 내용 |
org.springframework.jdbc.core | JdbcTemplate 및 관련 Helper 객체 제공 |
org.springframework.jdbc.datasource | DataSource를 쉽게 접근하기 위한 유틸 클래스, 트랜젝션매니져 및 다양한 DataSource 구현을 제공 |
org.springframework.jdbc.object | RDBMS 조회, 갱신, 저장등을 안전하고 재사용 가능한 객제 제공 |
org.springframework.jdbc.support | jdbc.core 및 jdbc.object를 사용하는 JDBC 프레임워크를 지원 |
JDBC Template
- org.springframework.jdbc.core 에서 가장 중요한 클래스
- 리소스 생성, 해지를 처리해 연결을 닫는 것을 잊어 발생하는 문제를 피할수 있게 도와준다.
- statement 의 생성과 실행을 처리
- sql 조회,업데이트, 저장 프로시저 호출, resultset 반복 호출 등을 실행
- jdbc 예외가 발생할 경우 org.springframework.dao 패키지에 정의되어있는 일반적인 예외로 변환 시킴
DTO ( Data Transfer Object )
컨트롤러와 뷰 그리고 비즈니스 계층간의 데이터 교환을 위한 java Beans입니다. 일반적으로 DTO는 로직을 가지고 있지 않은 순수한 데이터 객체입니다. 필드와 getter, setter를 가지며 toString(), equals(), hashCode()등의 Object 메소드를 오버라이딩 할 수 있습니다.
product.java ( DTO 예제 )
public class Book {
private Long id;
private String title;
private String content;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "Guestbook [id=" + id + ", title=" + title + ", content=" + content +"]";
}
}
DAO ( Data Access Object )
데이터 조회하거나 조작하는 기능 (select, insert,update, delete) 기능을 전담하도록 만든 객체입니다.
BookDaoSqls.java
public static final String SELECT_BY_ROLE_ID = "SELECT id, description FROM book where id = :bookId";
public static final String DELETE_BY_ROLE_ID = "DELETE FROM book WHERE id = :bookId";
sql문들만 모여있는 java 파일
BookDao.java
package kr.or.connect.daoexam.dao;
import static kr.or.connect.daoexam.dao.RoleDaoSqls.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.stereotype.Repository;
import kr.or.connect.daoexam.dto.Role;
@Repository
public class BookDao {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
private RowMapper<Role> rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
public BookDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("role");
}
public int deleteById(Integer id) {
Map<String, ?> params = Collections.singletonMap("bookId", id);
return jdbc.update(DELETE_BY_BOOK_ID, params);
}
public Role selectById(Integer id) {
try {
Map<String, ?> params = Collections.singletonMap("bookId", id);
return jdbc.queryForObject(SELECT_BY_ROLE_ID, params, rowMapper);
}catch(EmptyResultDataAccessException e) {
return null;
}
}
}
deleteById : book id로 데이터베이스에서 삭제하는 함수
selectById : book id에 해당하는 데이터 하나 가져오는 함수
DataSource
커넥션 풀을 관리하는 목적으로 사용되는 객체로 DataSource를 이용해 커넥션을 얻어오고 반납하는 등의 작업을 수행합니다.
커넥션 풀(Connection poll) 이란?
DB연결은 많은 비용이 들기 때문에, 커넥션 풀에 커넥션들을 미리 여러개 맺어두어 저장해두는 공간입니다. 커넥션이 필요하면 커넥션 풀에서 가져와 사용한 후 반납합니다. 만약 커넥션을 사용 후 반납하지 않는 상황이 지속된다면, 더이상 꺼내 사용할 커넥션이 없어져 프로그램 실행이 지연되거나 장애가 발생할 수 있습니다.
DBConfig.java
package kr.or.connect.daoexam.config;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@Configuration
@EnableTransactionManagement
public class DBConfig {
private String driverClassName = "com.mysql.jdbc.Driver";
private String url = "jdbc:mysql://localhost:3306/connectdb?useUnicode=true&characterEncoding=utf8";
private String username = "connectuser";
private String password = "connect123!@#";
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
private String url, private String username, private password 개인 설정에 맞게 바꿔줍니다.
실행소스
JDBCTest.java
package kr.or.connect.daoexam.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import kr.or.connect.daoexam.config.ApplicationConfig;
import kr.or.connect.daoexam.dao.RoleDao;
import kr.or.connect.daoexam.dto.Role;
public class JDBCTest {
public static void main(String[] args) {
ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
RoleDao bookDao = ac.getBean(bookDao.class);
Book resultBook = bookDao.selectById(201);
System.out.println(resultBook);
int deleteCount = bookDao.deleteById(500);
System.out.println(deleteCount + "건 삭제하였습니다.");
Role resultRole2 = bookDao.selectById(500);
System.out.println(resultRole2);
}
}