[Spring] MyBatis로 DAO 작성

Jeini·2023년 5월 29일
0

🍃  Spring

목록 보기
23/33
post-thumbnail

💡 BoardDao 작성


1️⃣ DB 테이블 생성

2️⃣ Mapper XML & DTO 작성

  • 데이터베이스 테이블로 부터 데이터를 CRUD를 하기 위한 sql문들을 작성

  • select를 하기 위한 resultType을 BoardDto로 설정

3️⃣ DAO 인터페이스 작성

4️⃣ DAO 인터페이스 구현 & 테스트

  • 나중에 DAO가 바뀔 때 (데이터베이스 종류 등) @Service쪽에 영향을 받지 않게 class가 아닌 인터페이스로 주입받게 함

  • Mapper 작성한 다음에 바로 구현해도 된다.
    ➡️ Extract Interface 기능(intelliJ)을 쓰면 바로 인터페이스 만들 수 있음

  • JDBC 할 떄는 우리가 값도 세팅해주고 실행할 결과를 우리가 직접 꺼내서 써야 됐는데, MyBatic는 값을 지정하고 읽어오는 것을 자동으로 해주기 때문에 우리는 단순히 sqlSession에 있는 메서드를 호출만 해주면 된다. 그리고 input 값들 알맞게 지정해 주기! result 타입에 알맞게 쓰기!

💡 DTO(Data Transfer Object)


✔️ 계층간의 데이터를 주고 받기 위해 사용되는 객체

  • int는 null이 뜨면 에러가 뜬다. ➡️ 변환 에러를 막기 위해 Integer 사용

  • 데이터베이스의 값들을 DTO로 옮긴다. 그래서 타입이름이랑 다 맞아야 한다.

✔️ 관심사, 역할, 계층 분리

  • 계층으로 분리를 해놓았기 때문에 각 계층마다 데이터를 주고 받아야 되는데 그 데이터를 DTO로 쓴다.

  • @Repository ➡️ DAO

  • DAO에서 Try-catch를 써서 예외를 처리하게 되면 커밋해야 될지 롤백해야 될지 트랜잭션에서는 모른다. 그래서 @Repository 에서는 예외처리를 하지 않는다. throws 해줘야 한다. @Service 에서 감당할 수 있는 부분만 예외처리 하고 할 수 없으면 @Contorller 로 던진다.

✏️ 실습


✔️ Mapper XML 작성

  • 이렇게 sql문으로 먼저 해보고 성공하면 input요소를 바꿔서 xml에다가 그대로 넣어준다.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.fastcampus.ch4.dao.BoardMapper">
    <select id="select" parameterType="int" resultType="BoardDto">
        select bno,
               title,
               content,
               writer,
               view_cnt,
               comment_cnt,
               reg_date,
               up_date
        from board
        where bno = #{bno}
    </select>
</mapper>

✏️ mybatis.xml에서 alias 설정으로 resultType 간단하게 적을 수 있게 된다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="BoardDto" type="kr.ac.jipark09.domain.BoardDto"/>
    </typeAliases>
</configuration>

✔️ DAO & DTO 작성

✏️ DAO

package kr.ac.jipark09.dao;

import kr.ac.jipark09.domain.BoardDto;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class BoardDao {
    @Autowired
    SqlSession session;
    String namespace = "kr.ac.jipark09.dao.BoardMapper.";

    public BoardDto select(int bno) throws Exception {
        return session.selectOne(namespace + "select", bno);
    }
}

✏️ DTO

package kr.ac.jipark09.domain;

import java.util.Date;
import java.util.Objects;

public class BoardDto {
    private Integer bno;
    private String title;
    private String content;
    private String writer;
    private int view_cnt;
    private int comment_cnt; // 댓글 갯수
    private Date reg_date;

    public BoardDto() {}

    public BoardDto(String title, String content, String writer) {
        this.title = title;
        this.content = content;
        this.writer = writer;
    }

    public Integer getBno() {
        return bno;
    }

    public void setBno(Integer bno) {
        this.bno = bno;
    }

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

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public int getView_cnt() {
        return view_cnt;
    }

    public void setView_cnt(int view_cnt) {
        this.view_cnt = view_cnt;
    }

    public int getComment_cnt() {
        return comment_cnt;
    }

    public void setComment_cnt(int comment_cnt) {
        this.comment_cnt = comment_cnt;
    }

    public Date getReg_date() {
        return reg_date;
    }

    public void setReg_date(Date reg_date) {
        this.reg_date = reg_date;
    }

    @Override
    public String toString() {
        return "BoardDto{" +
                "bno=" + bno +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", writer='" + writer + '\'' +
                ", view_cnt=" + view_cnt +
                ", comment_cnt=" + comment_cnt +
                ", reg_date=" + reg_date +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        BoardDto boardDto = (BoardDto) o;
        return Objects.equals(bno, boardDto.bno) && Objects.equals(title, boardDto.title) && Objects.equals(content, boardDto.content) && Objects.equals(writer, boardDto.writer);
    }

    @Override
    public int hashCode() {
        return Objects.hash(bno, title, content, writer);
    }
}

✔️ DAO 인터페이스 구현 & 테스트

✏️ interface

✏️ Test

package kr.ac.jipark09.dao;

import kr.ac.jipark09.domain.BoardDto;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import static org.junit.Assert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"file:src/main/webapp/WEB-INF/spring/**/root-context.xml"})
public class BoardDaoImplTest {
    @Autowired
    BoardDao boardDao;

    @Test
    public void select() throws Exception {

        BoardDto boardDto = boardDao.select(1);
        System.out.println(boardDto);
        assertTrue(boardDto.getBno().equals(1));

    }
}

💡 #{} 와 ${}의 차이


✔️ #{} ➡️ PreparedStatment

  • sql문에서 값에대해서만 ?를 쓸 수 있다.
    : 타입에 따라서 따옴표를 달아주기 때문에 안붙여줘도 된다.

  • 기본적으로 이것을 사용한다.

✔️ ${} ➡️ Statement

  • 문자열을 구성하기 때문에 직접 따옴표를 달아줘야 한다.

  • 테이블 이름도 ${tableName}으로 써도 된다.
    ➡️ 제약이 적고 유연함
    ➡️ 하지만 보안에 취약함

  • 값을 동적으로 사용하기 위해 꼭 써야 한다면 내부적으로만 사용해야 한다.

💡 XML의 특수 문자 처리


✔️ XML내의 특수 문자(<, >, $, ...)는 < >로 변환 필요
✔️ 특수문자가 포함된 쿼리를 <![CDTA[...]]>로 감싼다.

  • 특수문자인 태그로 오인할 수 있기 때문에 &lt; &gt; 이렇게 바꿔줘야 한다.
    하지만 <![CDTA[... ]]> 로 감싸면 특수문자를 사용할 수 있게 된다. 이 안에서는 XML태그가 없다라는 것을 명시하게 된다. 전부 Character data라는 것

Reference
: https://fastcampus.co.kr/dev_academy_nks

profile
Fill in my own colorful colors🎨

0개의 댓글