Spring

[SpringBoot] MyBatis

shb 2022. 5. 13. 16:53

XML과 애너테이션(annotation)을 사용하여 ‘저장 프로시저’나 ‘SQL 문’으로 ‘객체’들을 연결(매핑)시킨다.
(SQL Mapper 라고도 한다)

** 과거 아파치재단 에서 iBATIS로 개발했으나, 그 개발진들이 ‘구글코드’로 옮기면서 MyBatis로 이름을 바꾸어 계속 업데이트중.  (iBATIS 는 중단됨)

 

더 많이 코드를 줄일수 있고, 자바 코드가 아닌 ‘XML매퍼파일’ 을 통해서 DB에 접근 가능. 매우 간단
XML매퍼파일에 쿼리(SQL) 만 설정해두어도 알아서 동작 
(기존의 Connection 만들던 방식, JdbcTemplate 을 사용하던 방식 다 필요 없어짐)

 

Mybatis 프레임워크

자바코드(** DAO) <-> XML 매퍼파일, SQL 세팅 -> DB

DAO는 인터페이스로만 주어지고, MyBatis가 DAO를 구현해준다.

<mappper>는 어느 DAO에 매핑될지 지정
<mapper>는 여러 <SQL세팅>으로 구성. 각 <SQL세팅>은 DAO의 어느 메소드에 매핑될지 지정

 

MyBatis의 Mapper : JAVA 객체와 SQL 연동
MyBatis에서 Mapper 역할을 하는 매핑파일(XML)은 ‘데이터’ 조작을 하는 객체와 쿼리(SQL)를 연결(mapping)한다.   

‘데이터’ 조작을 하는 객체는 일반적으로 DAO객체가 그 역할을 하고 있다.

 

MyBatis : 한글 페이지
마이바티스 한글 : http://www.mybatis.org/mybatis-3/ko/
마이바티스 스프링 설정 : http://www.mybatis.org/spring/ko/sample.html
마이바티스 매퍼XML 설정 : http://www.mybatis.org/mybatis-3/ko/sqlmap-xml.html
마이바티스 매퍼설정: http://www.mybatis.org/mybatis-3/ko/configuration.html
그 밖에도 다양한 예제, 레퍼런스들 있음

 


MVC 기본 구조 작성

기존의 view (jsp) 파일들 가져오기, 기존 EL, JSTL 사용 버젼 가져오기
*.do 로 되어 있는 url 들 변경하기

 

* domain : DTO 작성
기존의 DTO 가져오기

WriteDTO.java

package com.lec.spring.domain;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

//DTO : Data Transfer Object
//DAO 등과 연동하여 데이터를 실어 나르는 객체
//필요한 객체(entity) 만큼 작성
public class WriteDTO {
	private int uid;    //  wr_uid
	private String subject;  // wr_subject
	private String content;  // wr_content
	private String name;     // wr_name
	private int viewCnt;  // wr_viewcnt
	private LocalDateTime regDate;  // wr_regdate
	
	// 웹개발시...
	// 가능한, 다음 3가지는 이름을 일치시켜주는게 좋습니다.
	// 클래스 필드명 = DB 필드명 = form의 name명

	
	public int getUid() {
		return uid;
	}
	public void setUid(int uid) {
		this.uid = uid;
	}
	public String getSubject() {
		return subject;
	}
	public void setSubject(String subject) {
		this.subject = subject;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getViewCnt() {
		return viewCnt;
	}
	public void setViewCnt(int viewCnt) {
		this.viewCnt = viewCnt;
	}
	public LocalDateTime getRegDate() {
		return regDate;
	}
	// LocalDateTime 을 String 으로 리턴하는 getter
	public String getRegDateTime() {
		if(this.regDate == null) return "";
		return this.regDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
	}
	public void setRegDate(LocalDateTime regDate) {
		this.regDate = regDate;
	}

	// 개발할때 class 의 toString() 을 오버라이딩 해주면
	// 웹에 표현하거나, 디버깅이나 테스팅 하기 좋다.
	@Override
	public String toString() {
		return String.format("WriteDTO] %d: %s : %s : %s : %d : %s", 
				uid, subject, content, name, viewCnt, regDate);
	}
	
	
	
	
} // end DTO

 


* domain : DAO 작성
DAO는 interface로 작성
동작하는 ‘추상메소드’들 작성 ← 후에 MyBatis가 SQL 매핑하여 생성해주게 된다.

WriteDAO.java

package com.lec.spring.domain;
import java.util.List;

// MyBatis가 매핑할 인터페이스
public interface WriteDAO {
	
	// 새글 작성 <-- DTO
	public abstract int insert(WriteDTO dto);
	
	// 전체 SELECT
	public abstract List<WriteDTO> select();
		
	// 특정 uid 의 글 하나 SELECT --> List<DTO> 로 리턴
	public abstract List<WriteDTO> selectByUid(int uid);
	
	// 특정 uid 의 글 수정 <- DTO
	public abstract int update(WriteDTO dto);
	
	// 특정 uid 글 삭제하기
	public abstract int deleteByUid(int uid);
	
	// 특정 uid 글 조회수 증가
	public abstract int incViewCnt(int uid);
	
} // end DAO

* Controller 작성

BoardController.java

package com.lec.spring.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.lec.spring.domain.WriteDTO;
import com.lec.spring.service.BoardService;

@Controller
@RequestMapping("/board")
public class BoardController {

	private BoardService boardService;

	@Autowired
	public void setBoardService(BoardService boardService) {
		this.boardService = boardService;
	}


	public BoardController() {
		System.out.println("BoardController() 생성");
	}
	
	
	@RequestMapping("/list")
	public void list(Model model) {
		model.addAttribute("list", boardService.list());
	}
	
	@GetMapping("/write")
	public void write(Model model) {}
	
	@PostMapping("/writeOk")
	public void writeOk(WriteDTO dto, Model model) {
		model.addAttribute("result", boardService.write(dto));
		model.addAttribute("dto", dto);  // auto-generated key 
	}

	@GetMapping("/view")
	public void view(int uid, Model model) {
		model.addAttribute("list", boardService.viewByUid(uid));
	}
	
	@GetMapping("/update")
	public void update(int uid, Model model) {
		model.addAttribute("list", boardService.selectByUid(uid));
	}
	
	@PostMapping("/updateOk")
	public void updateOk(WriteDTO dto, Model model) {
		model.addAttribute("result", boardService.update(dto));
		model.addAttribute("dto", dto);
	}
	
	@RequestMapping("/deleteOk")
	public void deleteOk(int uid, Model model) {
		model.addAttribute("result", boardService.deleteByUid(uid));
	}
	
}

* Service 생성

BoardService.java

package com.lec.spring.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.lec.spring.domain.WriteDAO;
import com.lec.spring.domain.WriteDTO;

//Service 단.
//JSP MVC model2 의 Command 역할 비슷
//  Controller -> Commmand -> DAO

//- Transaction 담당
//Spring
//@Controller -> @Service -> DAO -> JdbcTemplate
@Service
public class BoardService {

	WriteDAO dao;
	
	@Autowired
	public void setDao(WriteDAO dao) {
		this.dao = dao;
	}
	
	public BoardService() {
		System.out.println("BoardServcie() 생성");		
	}

	public List<WriteDTO> list() {
		
		return dao.select();
	}

	@Transactional
	public List<WriteDTO> viewByUid(int uid) {
		// 트랜잭션 처리!
		// 1. 조회수 증가
		// 2. 글 하나 읽어오기
		dao.incViewCnt(uid);
		return dao.selectByUid(uid);
	}

	public int write(WriteDTO dto) {
		return dao.insert(dto);
	}

	public List<WriteDTO> selectByUid(int uid) {
		return dao.selectByUid(uid);
	}

	public int update(WriteDTO dto) {
		return dao.update(dto);
	}

	public int deleteByUid(int uid) {
		return dao.deleteByUid(uid);
	}
}

* DAO 구현체 작성
DAOImpl /
반복되는 MySQL Mapper를 주입받는 구현체

WriteDAOImple.java

package com.lec.spring.domain;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

@Repository
public class WriteDAOImpl implements WriteDAO {

	private WriteDAO mapper;
	
	@Autowired
	public WriteDAOImpl(SqlSession sqlSession) {
		System.out.println("WriteDAOImpl() 생성");
		// MyBatis 가 생성한 WriteDAO 의 mapper (구현체)를 받아온다.
		mapper = sqlSession.getMapper(WriteDAO.class);   
	}
	
	
	@Override
	public int insert(WriteDTO dto) {
		return mapper.insert(dto);
	}

	@Override
	public List<WriteDTO> select() {
		return mapper.select();
	}

	@Override
	public List<WriteDTO> selectByUid(int uid) {
		return mapper.selectByUid(uid);
	}

	@Override
	public int update(WriteDTO dto) {
		return mapper.update(dto);
	}

	@Override
	public int deleteByUid(int uid) {
		return mapper.deleteByUid(uid);
	}

	@Override
	public int incViewCnt(int uid) {
		return mapper.incViewCnt(uid);
	}

}

WriteDAO.xml

MyBatis의 Mapper : JAVA 객체와 SQL 연동
MyBatis에서 Mapper 역할을 하는 매핑파일(XML)은 ‘데이터’ 조작을 하는 객체와 쿼리(SQL)를 연결(mapping)한다.   

<?xml version="1.0" encoding="UTF-8"?>
http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.lec.spring.domain.WriteDAO">

	<select id="select" resultType="com.lec.spring.domain.WriteDTO">
		SELECT 
			wr_uid "uid", 
			wr_subject subject, 
			wr_content content, 
			wr_name name, 
			wr_viewcnt viewcnt, 
			wr_regdate regDate 
		FROM 
			test_write 
		ORDER BY 
			wr_uid DESC	
	</select>

	<select id="selectByUid" resultType="com.lec.spring.domain.WriteDTO">
		SELECT 
			wr_uid "uid", 
			wr_subject subject, 
			wr_content content, 
			wr_name name, 
			wr_viewcnt viewcnt, 
			wr_regdate regDate 
		FROM 
			test_write
		WHERE wr_uid = #{uid} 
	</select>

	<update id="incViewCnt" flushCache="true">
		UPDATE test_write
		SET wr_viewcnt = wr_viewcnt + 1
		WHERE wr_uid = #{param1}
	</update>
	
	<insert id="insert" flushCache="true"
		parameterType="com.lec.spring.domain.WriteDTO"
		useGeneratedKeys="true"
		keyColumn="wr_uid" keyProperty="uid">
		INSERT INTO test_write
			(wr_subject, wr_content, wr_name)
		VALUES
			(#{subject}, #{content}, #{name})	
	</insert>
	
	<update id="update" flushCache="true"
		parameterType="com.lec.spring.domain.WriteDTO">
		UPDATE test_write
		SET wr_subject = #{subject}, wr_content = #{content}
		WHERE wr_uid = #{uid}
	</update>
	
	<delete id="deleteByUid" flushCache="true">
		DELETE FROM test_write WHERE wr_uid = #{uid}
	</delete>
	
	
	
</mapper>

* Controller 의 handler 및 view 파일 준비
각 url 별로 일단 매개변수 없이 view 만 보이기
동작 확인

 

'Spring' 카테고리의 다른 글

[SpringBoot] Security - 회원가입 DB 인증  (0) 2022.05.16
[SpringBoot] Security  (0) 2022.05.16
[Spring Boot] Validation  (0) 2022.05.12
[SpringBoot] Request Parameter  (0) 2022.05.12
[SpringBoot] RequestMapping  (0) 2022.05.12