설정 사항

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.2.2</version>
</dependency>
JDBC 템플릿 삭제, Mybatis 설정 추가
<!--MyBatis 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:config/SqlMapConfig.xml"/>
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 생성자 전달 방식으로 전달 -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg ref="sqlSessionFactory"/>
</bean>
BoardVo만 지금 추가해놨지만 추가적으로 명시해야 하는 부분들은 typeAliases에다가 추가를 해주면 된다.
<?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 type="kr.spring.board.vo.BoardVO" alias="boardVO"/>
</typeAliases>
<mappers>
<!-- resource - 경로 형태로 위치를 지정해준다. -->
<mapper resource="kr/spring/board/dao/BoardMapper.xml"/>
</mappers>
</configuration>
package kr.spring.board.vo;
import java.sql.Date;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
public class BoardVO {
private int num;
@NotBlank
private String writer;
@NotBlank
private String title;
@NotBlank
private String passwd;
@NotEmpty
private String content;
private Date reg_date;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
@Override
public String toString() {
return "BoardVO [num=" + num + ", writer=" + writer + ", title=" + title + ", passwd=" + passwd + ", content="
+ content + ", reg_date=" + reg_date + "]";
}
}
Interface 형태로 생성
package kr.spring.board.dao;
import java.util.List;
import java.util.Map;
import kr.spring.board.vo.BoardVO;
// 구조를 넣기 위해 생성
public interface BoardDAO {
public void insertBoard(BoardVO board);
public int selectBoardCount();
// map으로 묶어서 보내기 object는 검색의 경우(지금은 검색이 없기 때문에 Integer를 보낸다)
// mybatis는 하나의 인자만 사용한다. 무조건적으로 map으로 묶어서 보내야한다. (규칙)
// 인자 1개(map), 반환 타입 1개
// Sql Session Template를 사용하기 때문에 규칙을 따라야 한다.
public List<BoardVO> selectBoardList(Map<String, Integer> map);
public BoardVO selectBoard(int num);
public void updateBoard(BoardVO board);
public void deleteBoard(int num);
}
@Override
public int selectBoardCount() {
return sqlSessionTemplate.selectOne("selectBoardCount");
}
@Override
public List<BoardVO> selectBoardList(Map<String, Integer> map) {
return sqlSessionTemplate.selectList("selectBoardList",map);
}
@Override
public BoardVO selectBoard(int num) {
return sqlSessionTemplate.selectOne("selectDetail", num);
}
@Override
public void updateBoard(BoardVO board) {
sqlSessionTemplate.selectOne("updateBoard", board);
}
@Override
public void deleteBoard(int num) {
sqlSessionTemplate.selectOne("deleteBoard", num);
}
package kr.spring.board.dao;
import java.util.List;
import java.util.Map;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import kr.spring.board.vo.BoardVO;
@Repository
public class BoardDAOImpl implements BoardDAO {
// sql session template를 사용하기 때문에 autowired를 통해 주입 받는다.
@Autowired
private SqlSessionTemplate sqlSessionTemplate;
@Override
public void insertBoard(BoardVO board) {
sqlSessionTemplate.insert("insertBoard", board);
}
@Override
public int selectBoardCount() {
// MyBatis 프레임워크에서 사용되는 메서드로, SQL 쿼리를 실행하여 단일 결과 값을 반환할 때 사용
// sql 문장을 읽어오는 식별자를 명시(ID)
// sql문장에 id를 부여하는데 해당 id를 제공
// int를 반환해줌
return sqlSessionTemplate.selectOne("selectBoardCount");
}
@Override
public List<BoardVO> selectBoardList(Map<String, Integer> map) {
// map 안에 key와 value가 함께 저장이 되어있다.
// ID ?에 전달할 Data 갖고 있음
return sqlSessionTemplate.selectList("selectBoardList",map);
}
@Override
public BoardVO selectBoard(int num) {
return sqlSessionTemplate.selectOne("selectDetail", num);
}
@Override
public void updateBoard(BoardVO board) {
sqlSessionTemplate.selectOne("updateBoard", board);
}
@Override
public void deleteBoard(int num) {
sqlSessionTemplate.selectOne("deleteBoard", num);
}
}
Board DAO의 Mapper
<select id="selectBoardCount" resultType="integer">
SELECT COUNT(*) FROM aboard
</select >
<![CDATA[에러가 발생하는 코드 내부 작성]]>) -> xml 문법 체크를 하지 않도록 설정하는 태그#{start} , #{end} 로 명시해야 한다 (Mybatis 규칙)<select id="selectBoardList" parameterType="map" resultType="boardVO">
SELECT * FROM(SELECT a.*,rownum rnum FROM (SELECT * FROM aboard ORDER BY num DESC)a)
<![CDATA[
WHERE rnum >= #{start} AND rnum <= #{end}
]]>
</select>
<insert id="insertBoard" parameterType="boardVO">
INSERT INTO aboard (num, writer, title, passwd, content, reg_date)
VALUES(aboard_seq.nextval,#{writer},#{title},#{passwd},#{content},SYSDATE)
</insert>
<!-- 글 수정하기 -->
<update id="updateBoard" parameterType="boardVO">
UPDATE aboard SET writer=#{writer}, title=#{title}, content=#{content} WHERE num=#{num}
</update>
<delete id="deleteBoard" parameterType="integer">
DELETE FROM aboard WHERE num=#{num}
</delete>
<?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="kr.spring.board.dao.BoardDAO">
<!-- 총 레코드 수 구하는 sql -->
<!-- 반환 타입 명시(클래스형으로 작성) alias가 있기 때문에 integer로 작성이 가능-->
<!-- BoardDAOImpl에서 명시했던 id와 동일하게 작성! -->
<select id="selectBoardCount" resultType="integer">
SELECT COUNT(*) FROM aboard
</select >
<!-- 목록 호출 -->
<select id="selectBoardList" parameterType="map" resultType="boardVO">
SELECT * FROM(SELECT a.*,rownum rnum FROM (SELECT * FROM aboard ORDER BY num DESC)a)
<![CDATA[
WHERE rnum >= #{start} AND rnum <= #{end}
]]>
</select>
<!-- 글 작성하기 -->
<insert id="insertBoard" parameterType="boardVO">
INSERT INTO aboard (num, writer, title, passwd, content, reg_date) VALUES(aboard_seq.nextval,#{writer},#{title},#{passwd},#{content},SYSDATE)
</insert>
<!-- 해당하는 글 불러오기 -->
<select id="selectDetail" parameterType="integer" resultType="boardVO">
SELECT * FROM aboard WHERE num = #{num}
</select>
<!-- 글 수정하기 -->
<update id="updateBoard" parameterType="boardVO">
UPDATE aboard SET writer=#{writer}, title=#{title}, content=#{content} WHERE num=#{num}
</update>
<!-- 글 삭제하기 -->
<delete id="deleteBoard" parameterType="integer">
DELETE FROM aboard WHERE num=#{num}
</delete>
</mapper>
package kr.spring.board.service;
import java.util.List;
import java.util.Map;
import kr.spring.board.vo.BoardVO;
public interface BoardService {
public void insertBoard(BoardVO board);
public int selectBoardCount();
public List<BoardVO> selectBoardList(Map<String, Integer> map);
public BoardVO selectBoard(int num);
public void updateBoard(BoardVO board);
public void deleteBoard(int num);
}
@Override
public int selectBoardCount() {
return boardDAO.selectBoardCount();
}
@Override
public List<BoardVO> selectBoardList(Map<String, Integer> map) {
return boardDAO.selectBoardList(map);
}
@Override
public void insertBoard(BoardVO board) {
boardDAO.insertBoard(board);
}
@Override
public void updateBoard(BoardVO board) {
boardDAO.updateBoard(board);
}
@Override
public void deleteBoard(int num) {
boardDAO.deleteBoard(num);
}
package kr.spring.board.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.spring.board.dao.BoardDAO;
import kr.spring.board.vo.BoardVO;
@Service
@Transactional
public class BoardServiceImpl implements BoardService{
@Autowired
private BoardDAO boardDAO;
@Override
public void insertBoard(BoardVO board) {
boardDAO.insertBoard(board);
}
@Override
public int selectBoardCount() {
return boardDAO.selectBoardCount();
}
@Override
public List<BoardVO> selectBoardList(Map<String, Integer> map) {
return boardDAO.selectBoardList(map);
}
@Override
public BoardVO selectBoard(int num) {
return boardDAO.selectBoard(num);
}
@Override
public void updateBoard(BoardVO board) {
boardDAO.updateBoard(board);
}
@Override
public void deleteBoard(int num) {
boardDAO.deleteBoard(num);
}
}
pageNum이라는 요청 매개변수를 받아 현재 페이지 번호로 사용
pageNum이 제공되지 않으면 기본값으로 1을 사용
@RequestParam(value = "pageNum", defaultValue = "1")
총 레코드 수를 구하고, 콘솔에 count된 값 출력
int count = boardService.selectBoardCount();
log.debug("<<count>> : " + count );
PagingUtil 객체를 생성하여 페이지 처리
currentPage는 현재 페이지, count는 총 게시물 수, 20은 한 페이지당 게시물 수, 10은 페이지 블록 수, "list.do"는 페이지 요청 URL
PagingUtil page = new PagingUtil(currentPage, count, 20,10,"list.do");
총 게시물 수가 0보다 크면, 페이지 시작과 끝 행 번호를 map에 담아 boardService를 통해 게시물 목록을 가져온다.
List<BoardVO> list = null;
if(count > 0) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("start", page.getStartRow());
map.put("end", page.getEndRow());
list = boardService.selectBoardList(map);
}
ModelAndView 객체를 생성하고, 뷰 이름을 "selectList"로 설정
또한, 게시물 수(count), 게시물 목록(list), 페이지 정보(page)를 모델에 추가 후 반환
ModelAndView mav = new ModelAndView();
mav.setViewName("selectList");
mav.addObject("count", count);
mav.addObject("list", list);
mav.addObject("page", page.getPage());
return mav;
@ModelAttribute
public BoardVO initCommand() {
return new BoardVO();
}
@GetMapping("/insert.do")
public String insertForm() {
return "insertForm";
}
@PostMapping("/insert.do")
public String submit(@Valid BoardVO vo, BindingResult result) {
// 로그 호출
log.debug("<<BoardVo>> : " + vo);
// 유효성 체크
if(result.hasErrors()) {
return insertForm();
}
// 글 삽입
boardService.insertBoard(vo);
return "redirect:/list.do";
}
num이라는 정수형 매개변수
반환 타입은 ModelAndView로, 이는 뷰의 이름과 모델 데이터를 포함하여 반환
boardService라는 서비스 객체의 selectBoard 메서드를 호출하여 num에 해당하는 게시판 글 불러옴
해당 메서드는 BoardVO 객체를 반환한다.
새로운 ModelAndView 객체를 생성하여 반환
첫 번째 인자는 뷰의 이름 selectDetail
두 번째 인자는 모델의 속성 이름인 board
세 번째 인자는 모델의 속성 값인 board 객체
이 반환 값은 뷰에서 board 데이터를 사용할 수 있도록 전달한다.
@RequestMapping("/detail.do")
public ModelAndView detail(int num) {
log.debug("<<num>> : " + num);
BoardVO board = boardService.selectBoard(num);
// 뷰 이름 속성명 속성값
return new ModelAndView("selectDetail", "board", board);
}
model.addAttribute("boardVO", boardService.selectBoard(num));
뷰에 전달할 데이터를 추가하는 메서드
boardVO는 뷰에서 사용할 데이터의 키, 해당 이름으로 데이터를 뷰에서 참조
num에 해당하는 게시물 정보를 가져오기 위해 서비스 계층의 selectBoard 메서드를 호출
selectBoard(num) 호출 결과를 boardVO라는 이름으로 모델에 추가
@GetMapping("/update.do")
public String updateForm(int num, Model model) {
model.addAttribute("boardVO", boardService.selectBoard(num));
return "updateForm";
}
@PostMapping("/update.do")
public String submitUpdate(@Valid BoardVO vo, BindingResult result) {
log.debug("<<UpdateBoardVO>> : "+ vo);
if(result.hasErrors()) {
return "updateForm";
}
// DB에서 저장된
BoardVO db_board = boardService.selectBoard(vo.getNum());
if(!db_board.getPasswd().equals(vo.getPasswd())) {
result.rejectValue("passwd", "invalidPassword");
return "updateForm";
}
boardService.updateBoard(vo);
return "redirect:/list.do";
}
BoardVO vo를 넣는 이유는 detail로 들어가서 삭제를 해야 하기 때문이다.@GetMapping("/delete.do")
public String deleteForm(BoardVO vo) {
return "deleteForm";
}
hasFieldErrors라는 메서드를 사용하여 필드를 지정하여 에러 확인을 해준다. @PostMapping("/delete.do")
public String submitDelete(@Valid BoardVO vo, BindingResult result) {
log.debug("<<Delete Board>> : " + vo);
if (result.hasFieldErrors("passwd")) {
return "deleteForm";
}
// DB에서 저장된
BoardVO db_board = boardService.selectBoard(vo.getNum());
if (!db_board.getPasswd().equals(vo.getPasswd())) {
result.rejectValue("passwd", "invalidPassword");
return "deleteForm";
}
boardService.deleteBoard(vo.getNum());
return "redirect:/list.do";
}
package kr.spring.board.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import kr.spring.board.service.BoardService;
import kr.spring.board.vo.BoardVO;
import kr.spring.util.PagingUtil;
@Controller
public class BoardController {
@Autowired
private BoardService boardService;
// 유효성 체크를 위한 폼 초기화
@ModelAttribute
public BoardVO initCommand() {
return new BoardVO();
}
// 로그 처리하기
private static final Logger log = LoggerFactory.getLogger(BoardController.class);
@RequestMapping("/list.do")
// pageutil 에서 사용하는 값
public ModelAndView getList(@RequestParam(value = "pageNum", defaultValue = "1") int currentPage) {
// 총 레코드 수
int count = boardService.selectBoardCount();
log.debug("<<count>> : " + count);
// 페이지 처리하기
PagingUtil page = new PagingUtil(currentPage, count, 20, 10, "list.do");
// 목록 호출하기
List<BoardVO> list = null;
if (count > 0) {
// map에 담겨서 넘기기 때문에 map 생성
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("start", page.getStartRow());
map.put("end", page.getEndRow());
list = boardService.selectBoardList(map);
}
ModelAndView mav = new ModelAndView();
// 뷰 이름 설정
mav.setViewName("selectList");
// 데이터 저장
mav.addObject("count", count);
mav.addObject("list", list);
mav.addObject("page", page.getPage());
return mav;
}
// 폼 호출하기
@GetMapping("/insert.do")
public String insertForm() {
return "insertForm";
}
// 폼 등록하기
@PostMapping("/insert.do")
public String submit(@Valid BoardVO vo, BindingResult result) {
// 로그 호출
log.debug("<<BoardVo>> : " + vo);
// 유효성 체크
if (result.hasErrors()) {
return insertForm();
}
// 글 삽입
boardService.insertBoard(vo);
return "redirect:/list.do";
}
// 글 상세보기
@RequestMapping("/detail.do")
public ModelAndView detail(int num) {
log.debug("<<num>> : " + num);
BoardVO board = boardService.selectBoard(num);
// 뷰 이름 속성명 속성값
return new ModelAndView("selectDetail", "board", board);
}
// 글 수정 폼 호출하기
@GetMapping("/update.do")
public String updateForm(int num, Model model) {
model.addAttribute("boardVO", boardService.selectBoard(num));
return "updateForm";
}
// 글 수정하기
@PostMapping("/update.do")
public String submitUpdate(@Valid BoardVO vo, BindingResult result) {
log.debug("<<UpdateBoardVO>> : "+ vo);
if(result.hasErrors()) {
return "updateForm";
}
// DB에서 저장된
BoardVO db_board = boardService.selectBoard(vo.getNum());
if(!db_board.getPasswd().equals(vo.getPasswd())) {
result.rejectValue("passwd", "invalidPassword");
return "updateForm";
}
boardService.updateBoard(vo);
return "redirect:/list.do";
}
// 글 삭제하기 폼 호출하기
@GetMapping("/delete.do")
public String deleteForm(BoardVO vo) {
return "deleteForm";
}
// 글 삭제하기
@PostMapping("/delete.do")
public String submitDelete(@Valid BoardVO vo, BindingResult result) {
log.debug("<<Delete Board>> : " + vo);
if (result.hasFieldErrors("passwd")) {
return "deleteForm";
}
// DB에서 저장된
BoardVO db_board = boardService.selectBoard(vo.getNum());
if (!db_board.getPasswd().equals(vo.getPasswd())) {
result.rejectValue("passwd", "invalidPassword");
return "deleteForm";
}
boardService.deleteBoard(vo.getNum());
return "redirect:/list.do";
}
}
자동 스캔 방법을 사용함
알리아스로 명시하는데 더 설정해야 하는 경우 ,를 사용해서 추가 가능하고, *를 통해서도 작성이 가능하다.
<!-- mybatis 설정 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 더 있는 경우에는 쉼표 하고 추가 명시하면 된다 -->
<!-- *을 써서 명시도 가능함 -->
<property name="typeAliasesPackage" value="kr.spring.board.vo"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- xml 파일 등록 -->
<property name="basePackage" value="kr.spring.board.dao"/>
</bean>
package kr.spring.board.vo;
import java.sql.Date;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
public class BoardVO {
private int num;
@NotBlank
private String writer;
@NotBlank
private String title;
@NotBlank
private String passwd;
@NotEmpty
private String content;
private Date reg_date;
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getWriter() {
return writer;
}
public void setWriter(String writer) {
this.writer = writer;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
@Override
public String toString() {
return "BoardVO [num=" + num + ", writer=" + writer + ", title=" + title + ", passwd=" + passwd + ", content="
+ content + ", reg_date=" + reg_date + "]";
}
}
상단의 코드와 동일하게 작성되어 있기 때문에 추가적은 설명은 없이 지나감
package kr.spring.board.controller;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import kr.spring.board.service.BoardService;
import kr.spring.board.vo.BoardVO;
import kr.spring.util.PagingUtil;
@Controller
public class BoardController {
@Autowired
private BoardService boardService;
//로그 처리(로그 대상 지정)
private static final Logger log =
LoggerFactory.getLogger(BoardController.class);
//유효성 체크를 위한 자바빈(VO) 초기화
@ModelAttribute
public BoardVO initCommand(){
return new BoardVO();
}
//글쓰기 폼 호출
@GetMapping("/insert.do")
public String form() {
return "insertForm";
}
//전송된 데이터 처리
@PostMapping("/insert.do")
public String submit(@Valid BoardVO vo,
BindingResult result) {
log.debug("<<BoardVO>> : " + vo);
//유효성 체크 결과 오류가 있으면 폼 호출
if(result.hasErrors()) {
return form();
}
//글쓰기
boardService.insertBoard(vo);
return "redirect:/list.do";
}
//목록
@RequestMapping("/list.do")
public ModelAndView getList(
@RequestParam(value="pageNum",
defaultValue="1") int currentPage) {
//총레코드 수
int count = boardService.selectBoardCount();
//페이지 처리
PagingUtil page =
new PagingUtil(currentPage,count,20,10,"list.do");
//목록 호출
List<BoardVO> list = null;
if(count > 0) {
Map<String,Integer> map =
new HashMap<String,Integer>();
map.put("start", page.getStartRow());
map.put("end", page.getEndRow());
list = boardService.selectBoardList(map);
}
ModelAndView mav = new ModelAndView();
//뷰 이름 설정
mav.setViewName("selectList");
//데이터 저장
mav.addObject("count", count);
mav.addObject("list", list);
mav.addObject("page", page.getPage());
return mav;
}
//글상세
@RequestMapping("/detail.do")
public ModelAndView detail(int num) {
BoardVO board =
boardService.selectBoard(num);
return new ModelAndView("selectDetail","board",board);
}
//수정 폼 호출
@GetMapping("/update.do")
public String formUpdate(int num,Model model) {
model.addAttribute("boardVO",
boardService.selectBoard(num));
return "updateForm";
}
//전송된 데이터 처리
@PostMapping("/update.do")
public String submitUpdate(@Valid BoardVO vo,
BindingResult result) {
log.debug("<<BoardVO>> : " + vo);
//유효성 체크 결과 오류가 있으면 폼 호출
if(result.hasErrors()) {
return "updateForm";
}
//비밀번호 일치 여부 체크
//DB에 저장된 비밀번호 구하기
BoardVO db_board =
boardService.selectBoard(vo.getNum());
//비밀번호 체크
if(!db_board.getPasswd().equals(vo.getPasswd())) {
result.rejectValue("passwd", "invalidPassword");
return "updateForm";
}
//글 수정
boardService.updateBoard(vo);
return "redirect:/list.do";
}
//글 삭제 폼 호출
@GetMapping("/delete.do")
public String formDelete(BoardVO vo) {
return "deleteForm";
}
//글 삭제 처리
@PostMapping("/delete.do")
public String submitDelete(@Valid BoardVO vo,
BindingResult result) {
log.debug("<<BoardVO>> : " + vo);
//유효성 체크 결과 오류가 있으면 폼 호출
//비밀번호 전송 여부만 체크
if(result.hasFieldErrors("passwd")) {
return "deleteForm";
}
//비밀번호 일치 여부 체크
//DB에 저장된 비밀번호 구하기
BoardVO db_board =
boardService.selectBoard(vo.getNum());
//비밀번호 체크
if(!db_board.getPasswd().equals(vo.getPasswd())) {
result.rejectValue("passwd", "invalidPassword");
return "deleteForm";
}
//글 삭제
boardService.deleteBoard(vo.getNum());
return "redirect:/list.do";
}
}
인터페이스는 윗 부분의 코드처럼 객체를 생성 할 수 없고, 객체 생성을 위해서는 클래스가 존재해야 한다. 그러나 어노테이션 방법을 사용하면 mybatis가 자동으로 implement를 해서 자동으로 생성해주기 때문에 클래스를 생성할 필요가 없어졌다.
어노테이션 @Insert를 사용해서 SQL Insert 구문을 작성할 수 있다.
#{} 객체의 속성값을 SQL 구문에 매핑할 수 있다.
해당하는 insert 구문은 컬럼명과 객체의 속성값을 모두 다 입력하면 코드가 길어지기 때문에 XML에 입력하는 것이 깔끔하겠지만 모든 값을 순서대로 작성해주면 그대로 잘 값이 입력되기 때문에 컬럼명은 생략 후 SQL문을 작성했다.
@Insert("INSERT INTO aboard VALUES(aboard_seq.nextval,#{writer},#{title},#{passwd},#{content},SYSDATE)")
public void insertBoard(BoardVO board);
@Select 어노테이션을 사용하여 SQL SELECT 구문을 작성할 수 있다.
@Select("SELECT COUNT(*) FROM aboard")
public int selectBoardCount();
글 목록은 SQL 구문이 길기 때문에 Board Mapper XML에 작성해주었다.
public List<BoardVO> selectBoardList(Map<String, Integer> map);
@Select 어노테이션을 사용하여 SQL Select 구문을 작성할 수 있다.
#{} num의 속성값을 SQL 구문에 매핑한다.
@Select("SELECT * FROM aboard WHERE num=#{num}")
public BoardVO selectBoard(int num);
@Update 어노테이션을 이용하여 SQL Update 구문을 작성할 수 있다.
#{} 객체의 속성값들을 SQL 구문에 매핑해준다.
@Update("UPDATE aboard SET writer=#{writer}, title=#{title}, content=#{content} WHERE num=#{num}")
public void updateBoard(BoardVO board);
@Delete 어노테이션을 사용하여 SQL Delete 구문을 작성할 수 있다.
#{} num의 속성값을 SQL 구문에 매핑한다.
@Delete("DELETE FROM aboard WHERE num=#{num}")
public void deleteBoard(int num);
package kr.spring.board.dao;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import kr.spring.board.vo.BoardVO;
// mybatis가 자동으로 implement 해서 생성시켜준다
public interface BoardMapper {
@Insert("INSERT INTO aboard VALUES(aboard_seq.nextval,#{writer},#{title},#{passwd},#{content},SYSDATE)")
public void insertBoard(BoardVO board);
@Select("SELECT COUNT(*) FROM aboard")
public int selectBoardCount();
public List<BoardVO> selectBoardList(Map<String, Integer> map);
@Select("SELECT * FROM aboard WHERE num=#{num}")
public BoardVO selectBoard(int num);
@Update("UPDATE aboard SET writer=#{writer}, title=#{title}, content=#{content} WHERE num=#{num}")
public void updateBoard(BoardVO board);
@Delete("DELETE FROM aboard WHERE num=#{num}")
public void deleteBoard(int num);
}
매퍼 파일(BoardMapperXML)과 Java 인터페이스(BoardMapper)를 연결하는데 두 이름이 동일해야한다. namespace 속성은 이 매퍼 파일이 kr.spring.board.dao.BoardMapper 인터페이스와 연관되어 있음을 나타낸다.
목록 불러오는 sql 문장만 xml에 명시하는 이유는 너무 길기 때문에 어노테이션 방식보다 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">
<!-- interface명칭과 xml의 명칭이 동일해야 한다 -->
<mapper namespace="kr.spring.board.dao.BoardMapper">
<!-- 목록 가져오기 , 아이디는 따로 명시하지 않았음 그러나 메소드 명을 아이디로 사용 가능함-->
<select id="selectBoardList" parameterType="map" resultType="boardVO">
SELECT * FROM(SELECT a.*,rownum rnum FROM (SELECT * FROM aboard ORDER BY num DESC)a)
<![CDATA[
WHERE rnum >= #{start} AND rnum <= #{end}
]]>
</select>
</mapper>
상단의 코드와 동일하게 쓰여있음
package kr.spring.board.service;
import java.util.List;
import java.util.Map;
import kr.spring.board.vo.BoardVO;
public interface BoardService {
public void insertBoard(BoardVO board);
public int selectBoardCount();
public List<BoardVO> selectBoardList(Map<String, Integer> map);
public BoardVO selectBoard(int num);
public void updateBoard(BoardVO board);
public void deleteBoard(int num);
}
상단의 코드와 동일하게 작성되어 있음
package kr.spring.board.service;
import java.util.List;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import kr.spring.board.dao.BoardMapper;
import kr.spring.board.vo.BoardVO;
@Service
@Transactional
public class BoardServiceImpl implements BoardService{
@Autowired
private BoardMapper boardMapper;
@Override
public void insertBoard(BoardVO board) {
boardMapper.insertBoard(board);
}
@Override
public int selectBoardCount() {
return boardMapper.selectBoardCount();
}
@Override
public List<BoardVO> selectBoardList(Map<String, Integer> map) {
return boardMapper.selectBoardList(map);
}
@Override
public BoardVO selectBoard(int num) {
return boardMapper.selectBoard(num);
}
@Override
public void updateBoard(BoardVO board) {
boardMapper.updateBoard(board);
}
@Override
public void deleteBoard(int num) {
boardMapper.deleteBoard(num);
}
}