wintertreey 님의 블로그
@MVC - MyBatis : 미니게시판 본문
db작업
create table springboard(
num int primary key,
author varchar(10) not null,
title varchar(30) not null,
content text,
bwrite datetime default now(),
readcnt int default 0);
프로젝트 생성
프로젝트 세팅
application.properties
spring.application.name=sprweb17mybatis_miniboard
server.port=80
spring.thymeleaf.cache=false
#mariadb server connect
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://127.0.0.1:3306/gooddb
spring.datasource.username=root
spring.datasource.password=123
#mybatis
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
이번에는 mybatis로 xml 사용 예정.
작업 흐름도
HTML >
Controller(@Controller) >
BoardBean
package pack.controller;
import lombok.Data;
@Data
public class BoardBean {
private int num, readcnt;
private String author, title, content, bwrite;
private String searchName, searchValue;
}
Dao(@Repository) > Interface(@Mapper) >
Board
package pack.model;
import lombok.Data;
@Data
public class Board {
private int num, readcnt;
private String author, title, content, bwrite;
}
mapper.xml(Sql문) >
HTML
모델 영역에 두 클래스가 존재하는것을 확인할 수 있다. 두 어노테이션의 차이를 다시 한번 확인해보자.
@Repository와 @Mapper
@Repository | @Mapper | |
프레임워크 | Spring Framework | MyBatis |
기능 | Data Access Object (DAO) 패턴을 구현하여 데이터베이스와의 상호작용을 처리하는 역할 | MyBatis의 매퍼 인터페이스를 등록하고 SQL 매핑을 처리하는 역할 |
주요 역할 | - DAO클래스를 빈을 자동으로 등록하여 스프링 컨테이너에서 관리 - 예외를 Spring의 DataAccessException으로 변환 |
- MyBatis에서 매퍼 인터페이스를 정의 - MyBatis의 SQL 매핑을 처리 |
메인화면
<body>
<a href="list">미니 게시판 목록(@MVC - MyBatis)</a>
</body>
ListController.java
package pack.controller;
import java.util.ArrayList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import pack.model.Board;
import pack.model.BoardDao;
@Controller
public class ListController {
@Autowired
private BoardDao dao;
@RequestMapping("list") //get, post 다 받겠다는 뜻
public String list(Model model) {
ArrayList<Board> list = (ArrayList<Board>)dao.list();
model.addAttribute("list", list);
return "list";
}
}
BoardDao.java
@Repository
public class BoardDao {
private Logger logger= LoggerFactory.getLogger(this.getClass());
@Autowired
private DataMapInterface mapInterface;
public List<Board> list(){
List<Board> list = null;
try {
list= mapInterface.selectList();
} catch (Exception e) {
logger.info("list err: "+e);
}
return list;
}
DataMapInterface.java
@Mapper
public interface DataMapInterface {
//추상메소드명은 mapper.xml의 id명과 일치시킬것
List<Board> selectList();
mapper.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="pack.model.DataMapInterface">
<select id="selectList" resultType="pack.model.Board">
select * from springboard order by num desc
</select>
list.html
<body>
<h3>🎄🧸 글 목록 (미니 게시판) 🧸🎄</h3>
<div>
<a th:href="@{insert}">글쓰기</a>
</div>
<table border="1">
<tr>
<th>번호</th><th>글 제목</th><th>작성자</th><th>조회수</th>
</tr>
<th:block th:if="${list.size>0}">
<tr th:each="data:${list}">
<td th:text="${data.num}">num</td>
<td>
<a th:href="@{/detail(num=${data.num})}" th:text="${data.title}">title</a>
</td>
<td th:text="${data.author}">author</td>
<td th:text="${data.readcnt}">readcnt</td>
</tr>
</th:block>
<!-- 검색 -->
<tr>
<td colspan="4">
<form th:action="@{search}" method="post">
검색대상 :
<select name="searchName">
<option value="author" selected="selected">작성자</option>
<option value="title">글제목</option>
</select>
<input type="text" name="searchValue">
<input type="submit" value="검색">
</form>
</td>
</tr>
</table>
</body>
글쓰기
insertController.java
@Controller
public class InsertController {
@Autowired
private BoardDao dao;
@RequestMapping(value="insert", method = RequestMethod.GET)
public String insert() {
return "insform";
}
insform.html
<h3>🎄❄️ 글 쓰기 ❄️🎄</h3>
<form th:action="@{insert}" method="post">
작성자 : <input type="text" name="author"><br>
글제목 : <input type="text" name="title" size="50"><br>
글내용 : <textarea rows="5" cols="50" name="content"></textarea><br>
<input type="submit" value="저장">
</form>
insertController
@RequestMapping(value="insert", method = RequestMethod.POST)
public String insertsubmit(BoardBean bean) {
boolean b = dao.insertData(bean);
System.out.println();
if(b) {
return "redirect:/list";
}else {
return "err";
}
}
Dao
public boolean insertData(BoardBean bean) {
boolean b = false;
int re= mapInterface.insert(bean);
if(re>0) b = true;
return b;
}
Interface
int insert(BoardBean bean);
mapper.xml
<insert id="insert" parameterType="pack.controller.BoardBean">
insert into springboard(num, author, title, content, bwrite, readcnt)
values((select max(num) +1 from springboard ali), #{author}, #{title}, #{content}, now(), 0)
</insert>
mariadb, mysql에서 서브쿼리쓸때 같은 테이블사용시 별명줘야함. 오라클은 괜찮음.
검색
searchController.java
@Controller
public class SearchController {
@Autowired
private BoardDao dao;
@RequestMapping("search")
public String search(BoardBean bean, Model model) {
ArrayList<Board> slist = (ArrayList<Board>)dao.search(bean);
model.addAttribute("list", slist);
return "list";
}
dao
public List<Board> search(BoardBean bean){
List<Board> slist = mapInterface.selectSearch(bean);
return slist;
}
interface
List<Board> selectSearch(BoardBean bean);
mapper.xml
<select id="selectSearch" parameterType="pack.controller.BoardBean" resultType="pack.model.Board">
select * from springboard where ${searchName} like concat('%',#{searchValue},'%') order by num desc
</select>
칼럼매핑시 $, 데이터매핑시 #
상세보기
detailcontroller
@Controller
public class DetailController {
@Autowired
private BoardDao dao;
@RequestMapping("detail")
public String search(@RequestParam("num") String num, Model model) {
Board board = dao.detail(num);
model.addAttribute("board", board);
return "detail";
}
dao
public Board detail(String num) {
//조회수 증가 후 상세보기처리
mapInterface.updateReadcnt(num);
Board board = mapInterface.selectOne(num);
return board;
}
interface
Board selectOne(String num);
void updateReadcnt(String num);
mapper.xml
<select id="selectOne" parameterType="String" resultType="pack.model.Board">
select * from springboard where num=#{num}
</select>
<update id="updateReadcnt" parameterType="string">
update springboard set readcnt=readcnt+1 where num=#{num}
</update>
detail.html
<h3>🎄❄️ 상세보기 ❄️🎄</h3>
<form name="frm" th:object="${board}">
글번호 : [[${board.num}]]
<input type="hidden" th:field="*{num}"><br>
작성자: <input type="text" th:field="*{author}"><br>
글제목: <input type="text" th:field="*{title}"><br>
글내용: <textarea rows="5" cols="50" th:field="*{content}"></textarea><br>
작성일: [[${board.bwrite}]]<br>
조회수: [[${board.readcnt}]]<br>
<input type="button" value="목록" id="btnList">
<input type="button" value="수정" id="btnUpdate">
<input type="button" value="삭제" id="btnDelete">
</form>
수정하기 삭제하기
detail 페이지에서 바로 수정 삭제 가능하도록 했다.
detail.html 상단 javascript
<script type="text/javascript">
window.onload= function(){
document.querySelector("#btnList").onclick=function(){
location.href="list";
}
document.querySelector("#btnUpdate").onclick=function(){
if(confirm("정말 수정할까요?")){
//입력자료 검사 생략..
frm.action="update";
frm.method="post";
frm.submit();
}
}
document.querySelector("#btnDelete").onclick=function(){
if(confirm("정말 삭제할까요?")){
//입력자료 검사 생략..
frm.action="delete";
frm.method="get";
frm.submit();
}
}
}
</script>
updateController
@RequestMapping(value="update", method = RequestMethod.POST)
public String updatesubmit(BoardBean bean) {
boolean b = dao.updateData(bean);
System.out.println();
if(b) {
return "redirect:/list";
}else {
return "err";
}
}
deleteController
@RequestMapping(value="delete", method = RequestMethod.GET)
public String deletesubmit(BoardBean bean) {
boolean b = dao.deleteData(bean);
System.out.println();
if(b) {
return "redirect:/list";
}else {
return "err";
}
}
dao
public boolean updateData(BoardBean bean) {
boolean b = false;
int re= mapInterface.update(bean);
if(re>0) b = true;
return b;
}
public boolean deleteData(BoardBean bean) {
boolean b = false;
int re= mapInterface.delete(Integer.toString(bean.getNum()));
if(re>0) b = true;
return b;
}
interface
int update(BoardBean bean);
int delete(String num);
mapper.xml
<update id="update" parameterType="pack.controller.BoardBean">
update springboard set author=#{author}, title=#{title}, content=#{content}
where num=#{num}
</update>
<delete id="delete" parameterType="string">
delete from springboard where num=#{num}
</delete>
전체 소스코드는 sprweb17mybatis_miniboard를 참고하자
https://github.com/yoonah0327/spring_source.git
GitHub - yoonah0327/spring_source
Contribute to yoonah0327/spring_source development by creating an account on GitHub.
github.com
'백엔드 > Spring' 카테고리의 다른 글
aspectJ pointcut 표현식 (0) | 2024.08.01 |
---|---|
리덕스 Redux. 구조분해 연산자. (1) | 2024.08.01 |
@MVC DB연동4 : Spring DATA JPA JpaRepository CRUD (2) | 2024.07.22 |
@MVC DB연동4 : Spring DATA JPA JpaRepository (0) | 2024.07.21 |
@MVC DB연동4 : Spring DATA JPA CrudRepository (0) | 2024.07.21 |