땅콩이 맛난고 먹이자

[부스트코스]{3. 웹 앱 개발: 예약서비스 1/4}(8. Spring JDBC - BE)_2. Spring JDBC 실습 본문

edwith_부스트코스_웹 프로그래밍

[부스트코스]{3. 웹 앱 개발: 예약서비스 1/4}(8. Spring JDBC - BE)_2. Spring JDBC 실습

pea_Nut 2020. 3. 19. 20:16

개념

 

 

 

#DTO란?

  • DTO란 Data Transfer Object의 약자
  • 계층간 데이터 교환을 위한 자바빈즈이다.
  • 여기서의 계층이란 컨트롤러 뷰, 비지니스 계층, 퍼시스턴스 계층을 의미한다.
  • 일반적으로 DTO는 로직을 가지고 있지 않고, 순수한 데이터 객체이다.
  • 필드와 getter, setter를 가진다. 추가적으로 toString(), equals(), hashCode()등의 Object 메소드를 오버라이딩 할 수 있다.

 

 

 

 

#DAO란?

  • DAO란 Data Access Object의 약자로 데이터를 조회하거나 조작하는 기능을 전담하도록 만든 객체이다.
  • 보통 데이터베이스를 조작하는 기능을 전담하는 목적으로 만들어진다.

 

 

 

 

#ConnectionPool 이란?

  • DB연결은 비용이 많이 든다.
  • 커넥션 풀은 미리 커넥션을 여러 개 맺어 둔다.
  • 커넥션이 필요하면 커넥션 풀에게 빌려서 사용한 후 반납한다.
  • 커넥션을 반납하지 않으면 어떻게 될까?

connection Pool

 

 

#DataSource란?

  • DataSource는 커넥션 풀을 관리하는 목적으로 사용되는 객체이다.
  • DataSource를 이용해 커넥션을 얻어오고 반납하는 등의 작업을 수행한다.

 

 

 

 

#Spring JDBC를 이용한 DAO작성 실습

 

 

 

 

 


 

 

실습 1_접속

#maven project 생성

 

 

pom.xml

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>kr.or.connect</groupId>
	<artifactId>daoexam</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>daoexam</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>4.3.5.RELEASE</spring.version>
	</properties>

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-tx</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- basic data source -->
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-dbcp2</artifactId>
			<version>2.1.1</version>
		</dependency>


		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.45</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.6.1</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

=> spring, mysql, datasource 등 필요한 라이브러리 추가하기

 

 

ApplicationConfig.java 

 

package kr.or.connect.daoexam.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration //config 어노테이션
@Import({DBConfig.class})  //DB는 따로 작성할 것이다.
public class ApplicationConfig {

}

=> 공장만들기

 

 

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;

    }
}

=> DB config

 

 

DataSourceTest.java

 

package kr.or.connect.daoexam.main;

import java.sql.Connection;

import javax.sql.DataSource;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import kr.or.connect.daoexam.config.ApplicationConfig;

public class DataSourceTest {

	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class);
		DataSource ds = ac.getBean(DataSource.class);
		Connection conn = null;
		try {
			conn = ds.getConnection();
			if(conn != null)
				System.out.println("접속 성공^^");
		}catch (Exception e) {
			e.printStackTrace();
		}finally {
			if(conn != null) {
				try {
					conn.close();
				}catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

}

=> DB 테스트 코드

 

 

dir

 

 

 

실습 2_select

 

#DTO 패키지

 

Role.java

 

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 + "]";
	}
	
}

=> Role DTO 생성, 각 값들을 Role 이라는 가방(객체) 안에 가지고 다닌다고 이해하자.

 

 

#DAO 패키지

 

RoleDaoSqls.java

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

=> 쿼리를 상수 형태로 작성, 상수는 항상 대문자, '_'로 띄어쓰기 표현

 

 

RoleDao.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 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(){ //select 하는 메서드 생성
		return jdbc.query(SELECT_ALL, Collections.emptyMap(), rowMapper);
        //jdbc가 제공하는 query 메소드 이용, 파라미터를 넘겨주기만 하면 됨
	}

}

=> Role DAO에 접근할 수 있는 객체 생성

 

 

ApplicationConfig.java 에 추가

@ComponentScan(basePackages = { "kr.or.connect.daoexam.dao" })

=> 어노테이션이 붙어있는 객체를 읽어와야하므로

 

 

SelectAllTest.java

package kr.or.connect.daoexam.main;

import java.util.List;

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 SelectAllTest {

	public static void main(String[] args) {
		ApplicationContext ac = new AnnotationConfigApplicationContext(ApplicationConfig.class); 
		
		RoleDao roleDao =ac.getBean(RoleDao.class);

		List<Role> list = roleDao.selectAll();
		
		for(Role role: list) {
			System.out.println(role);
		}

	}

}

=> 테스트 코드

 

 

dir

 

 

 

실습 3_한 건 select & delete

 

#쿼리, 메서드 추가

 

RoleDaoSqls.java에 추가

 

public static final String SELECT_BY_ROLE_ID = "SELECT role_id, description FROM role where role_id = :roleId";
public static final String DELETE_BY_ROLE_ID = "DELETE FROM role WHERE role_id = :roleId";

 

 

RoleDao.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 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 int deleteById(Integer id) {  //delete 메서드
		Map<String, ?> params = Collections.singletonMap("roleId", id);
		return jdbc.update(DELETE_BY_ROLE_ID, params);
	}
	
	public Role selectById(Integer id) {  //한 건 select
		try {
			Map<String, ?> params = Collections.singletonMap("roleId", id);
			return jdbc.queryForObject(SELECT_BY_ROLE_ID, params, rowMapper);		
		}catch(EmptyResultDataAccessException e) {
			return null;
		}
	}

}

=> delete 메서드와 한 건 select 메서드 (selectAll과의 차이점 주의)

 

 

JDBCTest.java에 추가

 

Role resultRole = roleDao.selectById(201);
System.out.println(resultRole);
		
int deleteCount = roleDao.deleteById(500);
System.out.println(deleteCount + "건 삭제하였습니다.");
	
Role resultRole2 = roleDao.selectById(500);
System.out.println(resultRole2);
		

 

 

 

 

 

 

 

 

 

 

#부스트코스 강의

https://www.edwith.org/boostcourse-web/lecture/20661/

 

[LECTURE] 2) Spring JDBC 실습 : edwith

들어가기 전에 이번 시간엔 실습을 통해 Spring JDBC에 대해 알아보도록 하겠습니다.     학습 목표 DTO와 DAO에 대한 개념을 이해합니다. Spring JDBC를 이용... - 부스트코스

www.edwith.org