본문 바로가기
Spring|Spring-boot

[Spring] Spring JDBCTemplate

by oncerun 2020. 7. 16.
반응형

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

 

테스트

 

반응형

댓글