Notice
Recent Posts
Recent Comments
Link
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

wintertreey 님의 블로그

@MVC - MyBatis : 미니게시판 본문

Spring

@MVC - MyBatis : 미니게시판

wintertreey 2024. 7. 22. 18:19

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>

 

 

4번글이 지워진것을 확인할 수 있다.

 

 

 

 

 

전체 소스코드는 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