CREATE TABLE `book` (
`book_id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`title` VARCHAR(200) NOT NULL,
`category` VARCHAR(200) NOT NULL DEFAULT '',
`price` INT NULL,
`insert_date` DATETIME NOT NULL DEFAULT NOW(),
PRIMARY KEY (`book_id`)
)
COLLATE='utf8mb4_general_ci'
;
pom.xml
x<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.9</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.7</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
src/main/webapp/WEB-INF/spring/root-context.xml
xxxxxxxxxx
<!-- for mysql -->
<bean id="dataSource"
class="org.apache.commons.dbcp2.BasicDataSource"
destroy-method="close">
<property name="driverClassName"
value="com.mysql.cj.jdbc.Driver" />
<property name="url"
value="jdbc:mysql://localhost:3306/jspdb?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8" />
<property name="username" value="root" />
<property name="password" value="rootpass" />
</bean>
<!-- for mybatis -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!-- property name="mapperLocations" value="classpath:/sqlmap/**/*_SQL.xml" / -->
<property name="configLocation" value="classpath:/sqlmap/mybatis-config.xml" />
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
xxxxxxxxxx
<?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>
<mappers>
<mapper resource="mapper/book-mapper.xml"/>
</mappers>
</configuration>
xxxxxxxxxx
<?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="book">
</mapper>
xxxxxxxxxx
@Repository
public class BookDao {
@Autowired
SqlSessionTemplate slqSessionTemplate;
public BookDao() {
System.out.println("@Repository 스프링 자동생성");
}
}
xxxxxxxxxx
package com.sample.book.service;
public interface BookService {
}
xxxxxxxxxx
package com.sample.book.service;
import org.springframework.beans.factory.annotation.Autowired;
import com.sample.book.dao.BookDao;
@Service // 없으면 @Autowired시 오류남
public class BookServiceImpl implements BookService{
@Autowired
BookDao bookDao;
public BookServiceImpl() {
System.out.println("@Service 스프링 자동 생성");
}
}
xxxxxxxxxx
package com.sample.book.controller;
import org.springframework.stereotype.Controller;
@Controller
public class BookController {
@Autowired
BookService bookService;
public BookController() {
System.out.println("@Controller 스프링 자동 생성");
}
}
xxxxxxxxxx
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%>
<html>
<head>
<title>책 생성하기</title>
</head>
<body>
<h1>책 생성하기</h1>
<form method="POST">
<p>제목 : <input type="text" name="title" /></p>
<p>카테고리 : <input type="text" name="category" /></p>
<p>가격 : <input type="text" name="price" /></p>
<p><input type="submit" value="저장" />
</form>
</body>
</html>
book/create
경로의 뷰를 보여 줌 xxxxxxxxxx
@RequestMapping(value="/create", method = RequestMethod.GET)
public ModelAndView create() {
return new ModelAndView("book/create"); // jsp 저장 위치와 파일명
}
xxxxxxxxxx
<?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="book">
<insert id="insert" parameterType="hashMap" useGeneratedKeys="true" keyProperty="book_id">
<![CDATA[
insert into book
(title, category, price)
values
(#{title}, #{category}, #{price})
]]>
</insert>
</mapper>
xxxxxxxxxx
public int insert(Map<String, Object> map) {
return slqSessionTemplate.insert("book.insert",map);
}
xxxxxxxxxx
@Override
public int create(Map<String, Object> map) {
return dao.insert(map);
}
<context:component-scan>
확인redirect:
: response 객체의 sendRedirect() 와 동일 xxxxxxxxxx
@RequestMapping(value = "/create", method = RequestMethod.POST)
public ModelAndView createPost(@RequestParam Map<String, String> map) {
// 값 받기 : @RequestParam 스프링이 자동으로 넣어줌
System.out.println(map);
// service
int rs = bookService.create(map);
ModelAndView mav = new ModelAndView();
if(rs == 1) {
mav.setViewName("redirect:/list");
}else {
mav.setViewName("redirect:/create");
}
return mav;
}
xxxxxxxxxx
<%@page import="java.util.HashMap"%>
<%@page import="java.util.Map"%>
<%@page import="java.util.List"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
// el,jstl 사용시 불필요
//List<Map<String, Object>> data = (List<Map<String, Object>>)request.getAttribute("data");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>list.jsp</title>
</head>
<body>
<h1>책 목록</h1>
<table border="1">
<tr><th>Title</th><th>Category</th><th>Price</th></tr>
<c:forEach var="b" items="${data}">
<tr><td><a href="detail?bookId=${b.book_id}">${b.title}</a></td>
<td>${b.category}</td>
<td>${b.price }</td></tr>
</c:forEach>
</table>
</body>
</html>
xxxxxxxxxx
<select id="select_list" parameterType="hashMap" resultType="hashMap">
<![CDATA[
select
book_id,
title,
category,
price,
insert_date
from
book
order by insert_date desc
]]>
</select>
Map<String, Object>
의 목록 List
타입xxxxxxxxxx
public List<Map<String, Object>> selectList(Map<String, Object> map) {
return this.sqlSessionTemplate.selectList("book.select_list", map);
}
xxxxxxxxxx
List<Map<String, Object>> list(Map<String, Object> map);
xxxxxxxxxx
@Override
public List<Map<String, Object>> list(Map<String, Object> map){
return this.bookDao.selectList(map);
}
xxxxxxxxxx
@RequestMapping(value = "list")
public ModelAndView list(@RequestParam Map<String, Object> map) {
List<Map<String, Object>> list = this.bookService.list(map);
ModelAndView mav = new ModelAndView();
mav.addObject("data", list);
mav.setViewName("/book/list");
return mav;
}
xxxxxxxxxx
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<head>
<title>책 목록</title>
</head>
<body>
<h1>책 목록</h1>
<table>
<thead>
<tr>
<td>제목</td>
<td>카테고리</td>
<td>가격</td>
</tr>
</thead>
<tbody>
<c:forEach var="row" items="${data}">
<tr>
<td>
<a href="/detail?bookId=${row.book_id}">
${row.title}
</a>
</td>
<td>${row.category}</td>
<td><fmt:formatNumber type="number" maxFractionDigits="3" value="${row.price}" /></td>
</tr>
</c:forEach>
</tbody>
</table>
<p>
<a href="create">생성</a>
</p>
</body>
</html>
http://localhost:8080/book/list
xxxxxxxxxx
<select id="select_detail" parameterType="hashMap" resultType="hashMap">
<![CDATA[
select
title,
category,
price,
insert_date
from
book
where
book_id = #{bookId}
]]>
</select>
xxxxxxxxxx
public Map<String, Object> selectDetail(Map<String, Object> map) {
return this.sqlSessionTemplate.selectOne("book.select_detail", map);
}
xxxxxxxxxx
@Override
public Map<String, Object> detail(Map<String, Object> map){
return this.bookDao.selectDetail(map);
}
xxxxxxxxxx
@RequestMapping(value = "/detail", method = RequestMethod.GET)
public ModelAndView detail(@RequestParam Map<String, Object> map) {
Map<String, Object> detailMap = this.bookService.detail(map);
ModelAndView mav = new ModelAndView();
mav.addObject("data", detailMap);
String bookId = map.get("bookId").toString();
mav.addObject("bookId", bookId);
mav.setViewName("/book/detail");
return mav;
}
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<fmt:formatDate value="${data.insert_date}" pattern="yyyy.MM.dd HH:mm:ss" />
xxxxxxxxxx
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<html>
<head>
<title>책 상세</title>
</head>
<body>
<h1>책 상세</h1>
<p>제목 : ${ data.title } </p>
<p>카테고리 : ${ data.category }</p>
<p>가격 : <fmt:formatNumber type="number" maxFractionDigits="3" value="${data.price}" /></p>
<p>입력일 : <fmt:formatDate value="${data.insert_date}" pattern="yyyy.MM.dd HH:mm:ss" /></p>
<p>
<a href="/update?bookId=${bookId}">수정</a>
</p>
<form method="POST" action="/delete">
<input type="hidden" name="bookId" value="${bookId}" />
<input type="submit" value="삭제" />
</form>
<p>
<a href="/list">목록으로</a>
</p>
</body>
</html>
xxxxxxxxxx
<%@ tag body-content="empty" pageEncoding="utf-8" %>
<%@ tag import="java.time.format.DateTimeFormatter" %>
<%@ tag trimDirectiveWhitespaces="true" %>
<%@ attribute name="value" required="true"
type="java.time.temporal.TemporalAccessor" %>
<%@ attribute name="pattern" type="java.lang.String" %>
<%
if (pattern == null) pattern = "yyyy-MM-dd HH:mm:ss";
%>
<%= DateTimeFormatter.ofPattern(pattern).format(value) %>
xxxxxxxxxx
<%@ taglib prefix="tf" tagdir="/WEB-INF/tags" %>
<p>입력일 : <tf:formatDateTime value="${data.insert_date}" pattern="yyyy-MM-dd HH:mm:ss" /></p>
xxxxxxxxxx
@RequestMapping(value = "/update", method = RequestMethod.GET)
public ModelAndView update(@RequestParam Map<String, Object> map) {
Map<String, Object> detailMap = this.bookService.detail(map);
ModelAndView mav = new ModelAndView();
mav.addObject("data", detailMap);
mav.setViewName("/book/update");
return mav;
}
xxxxxxxxxx
<%@ page pageEncoding="UTF-8" contentType="text/html;charset=utf-8"%>
<html>
<head>
<title>책 수정</title>
</head>
<body>
<h1>책 수정</h1>
<form action="update" method="POST">
수정할 ID:<input type="text" name="bookId" value="${ data.book_id }" readonly>
<p>제목 : <input type="text" name="title" value="${ data.title }" /></p>
<p>카테고리 : <input type="text" name="category" value="${ data.category }" /></p>
<p>가격 : <input type="text" name="price" value="${ data.price }" /></p>
<p><input type="submit" value="저장" />
</form>
</body>
</html>
<update
: 수정(UPDATE) 쿼리를 실행하기 위한 마이바티스 태그xxxxxxxxxx
<update id="update" parameterType="hashMap">
<![CDATA[
update book set
title = #{title},
category = #{category},
price = #{price}
where
book_id = #{bookId}
]]>
</update>
xxxxxxxxxx
public int update(Map<String, Object> map) {
return this.sqlSessionTemplate.update("book.update", map);
}
xxxxxxxxxx
@Override
public boolean edit(Map<String, Object> map) {
int affectRowCount = this.bookDao.update(map);
return affectRowCount == 1;
}
xxxxxxxxxx
@RequestMapping(value = "update", method = RequestMethod.POST)
public ModelAndView updatePost(@RequestParam Map<String, Object> map) {
ModelAndView mav = new ModelAndView();
boolean isUpdateSuccess = this.bookService.update(map);
if (isUpdateSuccess) {
String bookId = map.get("bookId").toString();
mav.setViewName("redirect:/detail?bookId=" + bookId);
}else {
mav = this.update(map);
}
return mav;
}
bookId
파라미터를 전달하면 책 정보가 삭제
<delete
태그는 삭제(DELETE) 쿼리를 실행하기 위한 마이바티스 태그
xxxxxxxxxx
<delete id="delete" parameterType="hashMap">
<![CDATA[
delete from book
where
book_id = #{bookId}
]]>
</delete>
xxxxxxxxxx
public int delete(Map<String, Object> map) {
return this.sqlSessionTemplate.delete("book.delete", map);
}
xxxxxxxxxx
boolean delete(Map<String, Object> map);
xxxxxxxxxx
@Override
public boolean remove(Map<String, Object> map) {
int affectRowCount = this.bookDao.delete(map);
return affectRowCount == 1;
}
xxxxxxxxxx
@RequestMapping(value = "/delete", method = RequestMethod.POST)
public ModelAndView deletePost(@RequestParam Map<String, Object> map) {
ModelAndView mav = new ModelAndView();
boolean isDeleteSuccess = this.bookService.delete(map);
if (isDeleteSuccess) {
mav.setViewName("redirect:/list");
}else {
String bookId = map.get("bookId").toString();
mav.setViewName("redirect:/detail?bookId=" + bookId);
}
return mav;
}
<if
문은 마이바티스에서 조건<select id="select_list"
수정xxxxxxxxxx
<select id="select_list" parameterType="hashMap" resultType="hashMap">
<![CDATA[
select
book_id,
title,
category,
price,
insert_date
from
book
where 1 = 1
]]>
<if test="keyword != null and keyword != ''">
and (title like CONCAT('%',#{keyword},'%') or category like CONCAT('%',#{keyword},'%'))
</if>
order by insert_date desc
</select>
xxxxxxxxxx
// 검색어 추가
if (map.containsKey("keyword")) {
mav.addObject("keyword", map.get("keyword"));
}
xxxxxxxxxx
<p>
<form>
<input type="text" placeholder="검색" name="keyword" value="${keyword}" />
<input type="submit" value="검색" />
</form>
</p>