Spring jdbc를 이용한 Dao개발에 대해서 알아봅니다.
DTO란?
DTO는 Data Transfer Object의 약자입니다.
계층 간 데이터 교환을 위한 자바 빈즈입니다.
여기서 계층이란 컨트롤러 뷰 , 비즈니스 계층, 퍼시스턴스 계층을 의미합니다.
일반적으로 DTO는 로직을 가지고 있지 않고, 순수한 데이터 객체입니다.
일반적인 Entity라고 할 수 있습니다. 필드와 getter, setter를 가지며 추가적으로 toString(), equals(), hashCode()등의 Object의 메서드를 오버 라이딩할 수 있습니다.
데이터를 한 번에 들고 다니는 용도라고 간단히 이야기할 수 있습니다.
DAO란?
DAO는 Data Access Object의 약자로 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 객체입니다.
보통은 데이터베이스를 조작하는 기능을 전담하는 목적으로 만들어집니다.
객체지향에서 객체는 SRP방식을 따르고 있는데 DAO는 딱 하나의 역할만을 하도록 만들어야 합니다.
.
DataSource란?
DataSource는 커넥션 풀을 관리하는 목적으로 사용되는 객체입니다.
DataSource를 이용해 커넥션을 얻어오고 반납하는 등의 작업을 수행합니다.
커넥션 풀을 위한 라이브러리
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.1.1</version>
</dependency>
구조는 다음과 같다
설정의 관련된 ApplicationConfig 클래스 생성
package kr.or.connect.daoexam.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@Configuration
@Import({DBConfig.class})
public class ApplicationConfig {
}
import를 통해 DBConfig.class의 설정 정도 또한 포함시킨다.
DBConfig 클래스 생성
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 final String DRIVER = "com.mysql.cj.jdbc.Driver";
private final String URL = "dataBaseUrl";
private String username = "id";
private String password = "password";
@Bean
public DataSource dataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(DRIVER);
dataSource.setUrl(URL);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
}
커넥션 풀을 위한 DataSource를 지정해줍니다.
접속 테스트
데이터 전송계층 DTO생성
package kr.or.connect.daoexam.dto;
public class Role {
private int roleId;
private String description;
public int getRoleId() {
return roleId;
}
public void setRoleId(int roleID) {
this.roleId = roleID;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@Override
public String toString() {
return "Role [roleId=" + roleId + ", description=" + description + "]";
}
//데이터확인을 위해 toString()오버라이드
}
sql문을 저장하는 DaoSqls생성
package kr.or.connect.daoexam.dao;
public class RoleDaoSqls {
public static final String SELECT_ALL = "SELECT role_id, description FROM role order by role_id";
}
데이터를 가지고 있는 DTO와 쿼리문을 가 진객 체인 DAOsqls객체도 생성했으니
이제는 Dao객체를 생성한다.
dao객체는 저장소의 역할을 한다는 것으로 @Repository어노테이션을 붙임
package kr.or.connect.daoexam.dao;
import javax.sql.DataSource;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository;
import kr.or.connect.daoexam.dto.Role;
@Repository
public class RoleDao {
private NamedParameterJdbcTemplate jdbc;
private RowMapper<Role> rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
public RoleDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
}
}
jdbcTemplate은 데이터를 바인딩할 때? 를 사용했다. sql문자열만 봤을 경우 어떤 값이 매핑되는지 알아보기 힘든 문제가 존재
NamedParameterJdbcTemplate은 이름을 이용해서 바인딩하거나 결과 값을 가져올 때 사용 가능
빈으로 등록한 Bean객체 중 DataSource를 찾아 jdbc를 생성합니다.
Spring 버전 4.3부터는 기본 생성자가 없다면 자동으로 객체를 주입해줍니다.
import static kr.or.connect.daoexam.dao.RoleDaoSqls.*;
sql문이 작성된 클래스에 접근하기 위해 static import구문 작성
public List<Role> selectAll(){
return jdbc.query(SELECT_ALL,Collections.emptyMap(), rowMapper);
}
1. sql문
2. 비어있는 맵 객체 sql문에 바인딩할 값이 있을 경우 전달 목적
3. select의 결과를 dto의 저장하는 목적
BeanPropertyRowMapper는 DBMS와 JAVA의 이름 규칙을 맞춰주는 기능을 가지고 있고 dto의 값을 자동으로 넣어준다.
따라서 DBMS의 칼럼명이 role_id라면 dto의 멤버 변수는 roleId로 해야 한다.
dao에 @Repository어노테이션이 붙어있는 클래스를 빈 등록을 위해
ApplicationConfig에서 ComponentScan(basePackages = {"kr.or.connect.daoexam.dao"})로등록 여러 개 패키지 설정 가능
test성공
daoSqls에 insert문은 추가해주지 않는다.
그렇기 때문에 dao에서 SimpleJdbcInsert객체를 사용
package kr.or.connect.daoexam.dao;
import static kr.or.connect.daoexam.dao.RoleDaoSqls.SELECT_ALL;
import java.util.Collections;
import java.util.List;
import javax.sql.DataSource;
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 RoleDao {
private NamedParameterJdbcTemplate jdbc;
private SimpleJdbcInsert insertAction;
private RowMapper<Role> rowMapper = BeanPropertyRowMapper.newInstance(Role.class);
public RoleDao(DataSource dataSource) {
this.jdbc = new NamedParameterJdbcTemplate(dataSource);
this.insertAction = new SimpleJdbcInsert(dataSource)
.withTableName("role");
}
public List<Role> selectAll(){
return jdbc.query(SELECT_ALL,Collections.emptyMap(), rowMapper);
}
public int insert(Role role) {
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
return insertAction.execute(params);
}
}
insert메서드는 role객체를 받으며 해당 객체의 데이터 값을 Map으로 변경한 뒤
맵 객체를 execute로 전달 그 후 값 저장.
테스트
update문
"UPDATE role set description = :description where role_id = :roleId";
쿼리 :부분에 데이터 바인딩할 것임
dao에 update메서드 추가.
public int update(Role role) {
SqlParameterSource params = new BeanPropertySqlParameterSource(role);
return jdbc.update(UPDATE, params);
}
테스트
1건 데이터와 delete
package kr.or.connect.daoexam.dao;
public class RoleDaoSqls {
public static final String SELECT_ALL = "SELECT role_id, description FROM role order by role_id";
public static final String UPDATE = "UPDATE role set description = :description where role_id = :roleId";
public static final String DELETE_BY_ROLE_ID = "DELETE FROM role WHERE role_id=:roldId";
public static final String SELECT_BY_ROLE_ID = "SELECT role_id, description FROM role where role_id = roleId";
}
쿼리문에 *는 최대한 쓰지 말자 의미 전달!
dao delete메서드 구현
public int deleteById(Integer id) {
Map<String, ?> params = Collections.singletonMap("roleId", id);
return jdbc.update(DELETE_BY_ROLE_ID,params);
}
selectById구현
public Role selectById(Integer id) {
try {
Map<String, ?> params = Collections.singletonMap("roleId", id);
return jdbc.queryForObject(SELECT_BY_ROLE_ID,params,rowMapper);
} catch (Exception e) {
return null;
}
}
테스트
'Spring|Spring-boot' 카테고리의 다른 글
레이어드 아키텍쳐 (0) | 2020.07.17 |
---|---|
[Spring] setting (0) | 2020.07.17 |
Material UI 모달창 디자인구현 (0) | 2020.07.16 |
[Spring-boot] 자동설정 (0) | 2020.06.26 |
[Spring] @InitBinder 애노테이션을 이용한 컨트롤러 범위 Vaildator (0) | 2020.06.24 |
댓글