Spring JDBC 실습

최준영·2021년 9월 27일
0
post-custom-banner

1. maven 프로젝트 생성




  • maven-archetype-quickstart
  • group id, artifact id는 패키지가 될 것이기 때문에 소문자로 지정한다.
  • artifact Id는 실제 프로젝트 이름을 기입한다.

2. pom.xml에 해당 코드 추가


  <properties>
    <spring.version>4.3.5.RELEASE</spring.version>
  </properties>

  <dependencies>
    <!-- Spring. 버전은 5.1 이상으로 해야 오류 x -->
    <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>
    
    <!-- JDBC 사용을 위함. 내 컴퓨터의 mysql 버전과 동일해야함 -->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.26</version>
    </dependency>
    
    <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>

추가 후 maven update

3. config 작성


관리 용이를 위해 config 패키지 생성

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
@Import({DBConfig.class})
public class ApplicationConfig {
}
  • @import를 이용하면 설정 파일을 여러개로 나누어서 사용 가능하다.
  • 데이터베이스 연결 관련 설정을 따로 빼서 관리한다.

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

4. DTO 파일 생성

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

5. Dao 파일 생성

Dao에 쓰일 sql 파일 생성

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";
}
  • static final을 붙여서 상수처럼 사용. 대문자_대문자 형식으로 변수명을 정한다.

Dao 파일 생성 - SELECTAll()

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.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);
  }
  
  public List<Role> selectAll() {
    return jdbc.query(SELECT_ALL, Collections.emptyMap(), rowMapper);
  }
}
  • import static으로 선언하면 RoleDaoSqls의 변수를 클래스 이름없이 바로 사용 가능하게 한다. RoleDaoSqls.SELECT_ALL 대신 SELECT_ALL으로 사용 가능
  • Dao는 @Repository를 붙여준다.

jdbc.query(SELECT_ALL, Collections.emptyMap(), rowMapper);

  • query() 메서드는 결과가 여러건이면 내부적으로 반복하면서 DTO를 생성하고, 생성한 DTO를 List에 담은 후 해당 List를 반환한다.
  • 첫번째 인자는 sql이다.
  • 두번째 인자는 비어있는 맵 객체 하나를 선언한다.
    • sql 문에 바인딩 할 값이 있을 경우에 바인딩 할 값을 전달할 목적으로 사용한다.
  • 세번재 인자는 만들어놓은 rowMapper 객체를 넣는다.
    • select의 한건, 한건의 결과를 DTO에 저장하는 목적으로 사용한다.
    • BeanPropertyRowMapper 객체를 이용해서 column의 값을 자동으로 DTO에 담아준다.

BeanPropertyRowMapper와 변수명

  • DBMS에서는 column 명에서 단어와 단어를 구분할 때 _를 사용한다.
    • DBMS에서는 대소문자 구분을 하지 않기 때문이다.
  • Java에서는 camel 표기법을 이용해서 단어와 단어가 만날 대 대문자를 사용한다.
  • BeanPropertyRowMapper는 DBMS와 Java의 이름 규칙을 맞춰주는 기능을 가지고 있다.

6. ApplicationConfig.java 에 @ComponentScan 추가


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

7. Dao에 insert, update, select, delete 기능 추가


insert

RoleDao.java에 추가

  public int insert(Role role) {
    SqlParameterSource params = new BeanPropertySqlParameterSource(role);
    return insertAction.execute(params);
  }
  • 이런 insert 문 같은 경우에는 primary key를 자동으로 생성하는 경우도 존재한다.
    • 이럴 때는 생성된 primary key 값을 다시 읽어오는 등의 기능을 하는 부분들이 필요하다. SimpleJdbcInsert 객체가 그런 기능을 가지고 있다.
    • 여기서는 primary key 값을 그냥 넣어준다.
  • 해당 Role 객체에 있는 값을 맵으로 바꿔준다. roleId 이름을 role_id로 알아서 바꾼다.
  • 이렇게 생성한 맵 객체를 SimpleJdbcInsert의 execute() 메서드의 파라미터로 전달하면
    값이 알아서 저장된다.

update

RoleDaosqls.java에 추가

 public static final String UPDATE = "UPDATE role SET description = :description WHERE ROLE_ID = :roleId";
  • ':값'은 바인딩 될 부분이다.

RoleDao.java에 추가

  public int update(Role role) {
    SqlParameterSource params = new BeanPropertySqlParameterSource(role);
    return jdbc.update(UPDATE, params);
  }
  • jdbc.update(UPDATE, params)의 첫번째 인자는 sql, 두번째 인자는 맵 객체(매핑시켜줄 값을 가진 객체)이다.

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에 추가

  public int deleteById(Integer id) {
    Map<String, ?> params = Collections.singletonMap("roleId", id);
    return jdbc.update(DELETE_BY_ROLE_ID, params);
  }

  public Role selectById(Integer id) {
    try {
      Map<String, ?> params = Collections.singletonMap("roleId", id);
      return jdbc.queryForObject(SELECT_BY_ROLE_ID, params, rowMapper);
    } catch (EmptyResultDataAccessException e) {
      return null;
    }
  }

delete

  • query문은 update에서와 유사하다
  • params는 update처럼 객체를 넣어서 map으로 바꿔주는 SqlParameterSource를 이용해도 상관 없지만, delete는 값이 하나만 들어오기 때문에 굳이 객체를 만들지 않는 방법을
    사용했다.

select

  • 1건 select할때는 queryForObject 메서드를 이용한다.
    • 첫번째 인자는 query문이다.
    • 두번째 인자는 넣어둔 roleId 값이 전달이 목적이다.
    • 세번째 인자는 만들어놓은 맵 객체이다.
  • 조건에 맞는 값이 없으면 Exception이 발생한다.
profile
do for me
post-custom-banner

0개의 댓글