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 |