Mybatis
๋ง์ด๋ฐํฐ์ค๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ํ SQL, ์ ์ฅํ๋ก์์ ๊ทธ๋ฆฌ๊ณ ๋ช๊ฐ์ง ๊ณ ๊ธ ๋งคํ์ ์ง์ํ๋ ํผ์์คํด์ค ํ๋ ์์ํฌ์ด๋ค.
Mybatis ๊ณต์ ์ฌ์ดํธ
ํผ์์คํด์ค ํ๋ ์์ํฌ
ํผ์์คํด์ค ํ๋ ์์ํฌ๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ์ํธ์์ฉ์ ๋จ์ํํ๊ณ ์ถ์ํํ๋ ์ํํธ์จ์ด ๋๊ตฌ์
๋๋ค. ์ด ๋๊ตฌ๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ฐ์๋ SQL ์ฟผ๋ฆฌ๋ฅผ ์ง์ ์์ฑํ๋ ๋์ ๊ฐ์ฒด ์งํฅ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๊ทผํ ์ ์์ต๋๋ค. Mybatis๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ํ SQL, ์ ์ฅํ๋ก์์ , ๊ทธ๋ฆฌ๊ณ ๋ช ๊ฐ์ง ๊ณ ๊ธ ๋งคํ์ ์ง์ํ๋ ํผ์์คํด์ค ํ๋ ์์ํฌ์
๋๋ค.
SQL Mapper
Mybatis๋ SQL Mapper ํํ๋ก ๋์ํฉ๋๋ค. ๊ฐ๋ฐ์๋ SQL ๋ฌธ์ฅ์ด๋ ์ ์ฅํ๋ก์์ ๋ฅผ ์ง์ ์์ฑํ๊ณ , Mybatis๋ ์ด๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ฌํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋งคํํ์ฌ ๋ฐํํฉ๋๋ค. ์ด๋ฌํ ๋ฐฉ์์ ํตํด ๊ฐ๋ฐ์๋ ์ง์ ์ ์ธ SQL ์์ฑ์ ๋ํ ์ ์ฐ์ฑ๊ณผ ์ ์ด๋ ฅ์ ๊ฐ์ง๋ฉด์๋, ๊ฐ์ฒด ์งํฅ์ ์ธ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํ ์ ์์ต๋๋ค.
Mybatis vs JPA
Mybatis์ JPA๋ ๋ชจ๋ ํผ์์คํด์ค ํ๋ ์์ํฌ์ด์ง๋ง, ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์๊ณผ ์ฒ ํ์ ๊ฐ์ง๊ณ ์์ต๋๋ค. JPA๋ ๊ฐ์ฒด-๊ด๊ณ ๋งคํ์ ์ค์ฌ์ผ๋ก ํ ORM(Object-Relational Mapping) ํ๋ ์์ํฌ์ด๋ฉฐ, ๊ฐ๋ฐ์๊ฐ ๊ฐ์ฒด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ํธ์์ฉํฉ๋๋ค. ๋ฐ๋ฉด Mybatis๋ SQL Mapper๋ก์ ์ง์ ์ ์ธ SQL ์์ฑ๊ณผ ๋งคํ์ ์ค์ฌ์ผ๋ก ํ ํ๋ ์์ํฌ์
๋๋ค. ์ด๋ค ํ๋ ์์ํฌ๋ฅผ ์ ํํ ์ง๋ ๊ฐ๋ฐ์์ ์ ํธ๋์ ํ๋ก์ ํธ ์๊ตฌ์ฌํญ์ ๋ฐ๋ผ ๊ฒฐ์ ๋ฉ๋๋ค.
Spring Framework ์ Mybatis ์ฐ๋
Mybatis๋ฅผ Spring Framework์ ์ฐ๋ํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
1.
Mybatis ์์กด์ฑ ์ค์
2.
Mybatis ์ค์ ๋ฐ ์ค์ ํ์ผ ์์ฑ
3.
SqlSessionFactoryBean๊ณผ SqlSessionTemplate ๋น ๋ฑ๋ก
4.
Mapper ์ธํฐํ์ด์ค ํจํค์ง ์ค์บ ๊ฒฝ๋ก ์ค์
5.
Mapper.xml ๋งคํ ํ์ผ ์์ฑ
6.
Mapper ์ธํฐํ์ด์ค ์์ฑ
7.
๋น์ฆ๋์ค ๋ก์ง ๊ตฌํ
Mybatis ์์กด์ฑ ์ค์
โข
pom.xml
โฆ
mybatis
โฆ
mybatis-spring
โฆ
spring-jdbc
โฆ
mysql-connector-java
โข
<!-- mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
XML
๋ณต์ฌ
<!-- mysql ๋๋ผ์ด๋ฒ -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.1.0</version>
</dependency>
<!-- Spring JDBC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${org.springframework-version}</version>
</dependency>
XML
๋ณต์ฌ
โข
lombok
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
XML
๋ณต์ฌ
Mybatis ์ค์ ๋ฐ ์ค์ ํ์ผ
Mybatis ๋ค์ ์คํ์ด์ค
โข
root-context.xml
xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
XML
๋ณต์ฌ
Mybatis ์คํค๋ง ์ค์
โข
root-context.xml
http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
XML
๋ณต์ฌ
SqlSessionFactoryBean, SqlSessionTemplate ๋น ๋ฑ๋ก
โข
root-context.xml
<!-- DriverManagerDataSource ๋น ๋ฑ๋ก -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/joeun"></property>
<property name="username" value="joeun"></property>
<property name="password" value="123456"></property>
</bean>
<!-- SqlSessionFactoryBean ๋น ๋ฑ๋ก -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/mybatis-config.xml"></property>
</bean>
<!-- MyBatis SqlSessionTemplate ๋น ๋ฑ๋ก -->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" destroy-method="clearCache">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory"></constructor-arg>
</bean>
XML
๋ณต์ฌ
Mapper ์ธํฐํ์ด์ค ํจํค์ง ์ค์บ ๊ฒฝ๋ก ์ค์
โข
root-context.xml
<!-- Mapper ์ธํฐํ์ด์ค ํจํค์ง ๊ฒฝ๋ก ์ค์ -->
<mybatis-spring:scan base-package="com.aloha.spring.mapper" />
XML
๋ณต์ฌ
Mybatis ์ค์ ํ์ผ
โข
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- ์ค์ -->
<settings>
<!-- ์ธ๋์ค์ฝ์ด ์ผ์ด์ค์ธ ์ปฌ๋ผ์ ์นด๋ฉ ์ผ์ด์ค๋ก ๋ณํํ๋ ์ค์ -->
<!-- no - no -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- ํ์
๋ณ์นญ ์ค์ -->
<typeAliases>
<!-- ํจํค์ง๋ถํฐ์ ์ ์ฒด๊ฒฝ๋ก๋ฅผ ๊ฐ๋ ์๋ฐ ํ์
์ ์ถ์ฝํด์ ๋ณ์นญ์ผ๋ก ์ง์ -->
<!--
<typeAlias alias="Board" type="com.aloha.spring.dto.Board"/>
<typeAlias alias="User" type="com.aloha.spring.dto.User"/>
<typeAlias alias="Comment" type="com.aloha.spring.dto.Comment"/>
-->
<!-- ํ
์ด๋ธ๊ณผ ๋งคํํ DTO๊ฐ ์๋ ํจํค์ง ๊ฒฝ๋ก ์ง์ -->
<package name="com.aloha.spring.dto"/>
</typeAliases>
</configuration>
XML
๋ณต์ฌ
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">
<!-- namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก" -->
<mapper namespace="com.aloha.spring.mapper.BoardMapper">
</mapper>
HTML
๋ณต์ฌ
โข
BoardMapper.xml
โฆ
โฆ
~/java
โช
com.aloha.spring.mapper
โฆ
~/resources
โช
com.aloha.spring.mapper
โข
BoardMapper.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">
<!-- namespace="๋งคํผ ์ธํฐํ์ด์ค ๊ฒฝ๋ก" -->
<mapper namespace="com.aloha.spring.mapper.BoardMapper">
<!-- sql ํ๊ทธ ์์ฑ -->
<!-- ๊ฒ์๊ธ ๋ชฉ๋ก -->
<!-- id : ์ฐ๊ฒฐํ ๋งคํผ ์ธํฐํ์ด์ค์ ๋ฉ์๋๋ช
-->
<!-- resultType : ์กฐํ ๊ฒฐ๊ณผ๋ฅผ ๋งคํํ ํด๋์ค ํ์
(ํจํค์ง๊ฒฝ๋ก+ํด๋์ค๋ช
) -->
<select id="list" resultType="com.aloha.spring.dto.Board">
SELECT no 'no'
,title
,writer
,content
,reg_date 'regDate'
,upd_date 'updDate'
,views
FROM board
</select>
<!-- ๊ฒ์๊ธ ์กฐํ -->
<!-- ๋งคํ ํ๋ผ๋ฏธํฐ : #{ํ๋ผ๋ฏธํฐ๋ช
} -->
<!-- #{} ํ๋ผ๋ฏธํฐ ๊ฐ์๊ฐ 1๊ฐ๋ผ๋ฉด, ์ด๋ฆ๊ณผ ๋ฌด๊ดํ๊ฒ ๋งคํ๋๋ค. -->
<select id="select" resultType="com.aloha.spring.dto.Board">
SELECT no 'no'
,title
,writer
,content
,reg_date 'regDate'
,upd_date 'updDate'
,views
FROM board
WHERE no = #{no}
</select>
<!-- ๊ฒ์๊ธ ๋ฑ๋ก -->
<!-- Mapper ์ธํฐํ์ด์ค์ ๋๊ฒจ์ค ํ๋ผ๋ฏธํฐ๊ฐ ์ฌ๋ฌ ๊ฐ๋ผ๋ฉด ๊ฐ์ฒด๋ก ๋งคํํ ์ ์๋ค. -->
<!-- ๋งค๊ฐ๋ณ์๋ก Board ํด๋์ค๋ฅผ ์ง์ ํ๋ฉด ๋ณ์๋ค์ด ์๋์ผ๋ก #{๋ณ์} ํ๋ผ๋ฏธํฐ์ ๋งคํ๋๋ค. -->
<!-- #{index} : ํ๋ผ๋ฏธํฐ๋ฅผ ์์๋๋ก index ๋ก ๋งคํํ์ฌ ์ฌ์ฉํ ์๋ ์๋ค. -->
<insert id="insert">
INSERT INTO board ( title, writer, content )
VALUES ( #{title}, #{writer}, #{content} )
<!-- (index๋ก ๋งคํํ๋ ๊ฒฝ์ฐ) VALUES ( #{0}, #{1}, #{2} ) -->
</insert>
<!-- ๊ฒ์๊ธ ์์ -->
<update id="update">
UPDATE board
SET title = #{title}
,writer = #{writer}
,content = #{content}
,upd_date = now()
WHERE no = #{no}
</update>
<!-- ๊ฒ์๊ธ ์ญ์ -->
<delete id="delete">
DELETE FROM board
WHERE no = #{no}
</delete>
</mapper>
XML
๋ณต์ฌ
Mapper ์ธํฐํ์ด์ค ์์ฑ
โข
BoardMapper.java
@Mapper
public interface BoardMapper {
// ๋ฉ์๋ ๋ช
์ Mapper.xml ๋งคํ ํ์ผ์ SQL ํ๊ทธ id ๊ฐ๊ณผ ์ผ์นํด์ผํ๋ค.
public List<Board> list() throws Exception;
public Integer insert(Board board) throws Exception;
public Board select(Integer no) throws Exception;
public Integer update(Board board) throws Exception;
public Integer delete(Integer no) throws Exception;
}
Java
๋ณต์ฌ
table
CREATE TABLE `board` (
`no` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`writer` varchar(100) NOT NULL,
`content` text,
`reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`upd_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`views` int NOT NULL DEFAULT '0',
PRIMARY KEY (`no`)
) COMMENT='๊ฒ์ํ';
SQL
๋ณต์ฌ
โข
์ํ ๋ฐ์ดํฐ
INSERT INTO `board` (`title`, `writer`, `content`, `views`)
VALUES
('์ฒซ ๋ฒ์งธ ๊ธ', '์์ฑ์1', '์ฒซ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 5),
('๋ ๋ฒ์งธ ๊ธ', '์์ฑ์2', '๋ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 12),
('์ธ ๋ฒ์งธ ๊ธ', '์์ฑ์3', '์ธ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 8),
('๋ค ๋ฒ์งธ ๊ธ', '์์ฑ์4', '๋ค ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 20),
('๋ค์ฏ ๋ฒ์งธ ๊ธ', '์์ฑ์5', '๋ค์ฏ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 7),
('์ฌ์ฏ ๋ฒ์งธ ๊ธ', '์์ฑ์6', '์ฌ์ฏ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 15),
('์ผ๊ณฑ ๋ฒ์งธ ๊ธ', '์์ฑ์7', '์ผ๊ณฑ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 3),
('์ฌ๋ ๋ฒ์งธ ๊ธ', '์์ฑ์8', '์ฌ๋ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 9),
('์ํ ๋ฒ์งธ ๊ธ', '์์ฑ์9', '์ํ ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 22),
('์ด ๋ฒ์งธ ๊ธ', '์์ฑ์10', '์ด ๋ฒ์งธ ๊ธ์ ๋ด์ฉ์
๋๋ค.', 0);
SQL
๋ณต์ฌ
๋น์ฆ๋์ค ๋ก์ง
โข
Board.java
โข
BoardService.java
โข
BoardServiceImpl.java
Board.java
@Data
public class Board {
private int no;
private String title;
private String writer;
private String content;
private Date regDate;
private Date updDate;
private int views;
public Board() {
}
public Board(String title, String writer, String content) {
this.title = title;
this.writer = writer;
this.content = content;
}
}
Java
๋ณต์ฌ
BoardService.java
public interface BoardService {
// ๊ฒ์๊ธ ๋ชฉ๋ก
public List<Board> list() throws Exception;
// ๊ฒ์๊ธ ์กฐํ
public Board select(int no) throws Exception;;
// ๊ฒ์๊ธ ๋ฑ๋ก
public Integer insert(Board board) throws Exception;
// ๊ฒ์๊ธ ์์
public Integer update(Board board) throws Exception;
// ๊ฒ์๊ธ ์ญ์
public Integer delete(int no) throws Exception;
}
Java
๋ณต์ฌ
BoardServiceImpl.java
@Service // ๋น์ฆ๋์ค ๋ก์ง์ ์ฒ๋ฆฌํ๋ ์๋น์ค ํด๋์ค๋ก ๋น ๋ฑ๋ก
public class BoardServiceImpl implements BoardService {
private static final Logger logger = LoggerFactory.getLogger(BoardServiceImpl.class);
@Autowired
private BoardMapper boardMapper;
@Override
public List<Board> list() throws Exception {
List<Board> boardList = boardMapper.list();
return boardList;
}
@Override
public Board select(int no) throws Exception {
Board board = boardMapper.select(no);
return board;
}
@Override
public Integer insert(Board board) throws Exception {
int result = boardMapper.insert(board);
return result;
}
@Override
public Integer update(Board board) throws Exception {
int result = boardMapper.update(board);
return result;
}
@Override
public Integer delete(int no) throws Exception {
int result = boardMapper.delete(no);
return result;
}
}
Java
๋ณต์ฌ
์ปจํธ๋กค๋ฌ
BoardController.java
package com.aloha.spring.controller;
import java.util.List;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.aloha.spring.dto.Board;
import com.aloha.spring.service.BoardService;
@Controller // ์ปจํธ๋กค๋ฌ๋ก ๋น ๋ฑ๋ก
@RequestMapping("/board") // ํด๋์ค ๋ ๋ฒจ ๊ฒฝ๋ก /board ๋ก ์ง์
public class BoardController {
private static final Logger logger
= LoggerFactory.getLogger(BoardController.class);
@Autowired // ์์กด์ฑ ์๋ ์ฃผ์
private BoardService boardSerivce;
/**
* ๊ฒ์๊ธ ๋ชฉ๋ก
* @param model
* @return
* @throws Exception
*/
// @RequestMapping(value = "/list", method = RequestMethod.GET)
@GetMapping("/list") // Spring 4.3 ๋ฒ์ ์ฌ์ฉ ๊ฐ๋ฅ
public String list(Model model) throws Exception {
List<Board> boardList = boardSerivce.list();
model.addAttribute("boardList", boardList);
return "board/list"; // board/list.jsp ํ๋ฉด ์๋ต
}
/**
* ๊ฒ์๊ธ ์กฐํ
* @param model
* @param no
* @return
* @throws Exception
*/
@GetMapping("/read")
public String read(Model model, int no) throws Exception {
Board board = boardSerivce.select(no);
model.addAttribute("board", board);
return "board/read";
}
// ๊ฒ์๊ธ ๋ฑ๋ก - /board/insert - [GET]
@GetMapping("/insert")
public String insert() throws Exception {
return "board/insert";
}
// ๊ฒ์๊ธ ๋ฑ๋ก ์ฒ๋ฆฌ - /board/insert - [POST]
@PostMapping("/insert")
public String insertPro(Board board) throws Exception {
int result = boardSerivce.insert(board);
logger.info("๊ฒ์๊ธ ๋ฑ๋ก ์์ฒญ - result : " + result);
return "redirect:/board/list";
}
// ๊ฒ์๊ธ ์์ - /board/update - [GET]
@GetMapping("/update")
public String update(Model model, int no) throws Exception {
Board board = boardSerivce.select(no);
model.addAttribute("board", board);
return "board/update";
}
// ๊ฒ์๊ธ ์์ ์ฒ๋ฆฌ - /board/update - [POST]
@PostMapping("/update")
public String updatePro(Board board) throws Exception {
int result = boardSerivce.update(board);
logger.info("๊ฒ์๊ธ ์์ ์์ฒญ - result : " + result);
return "redirect:/board/list";
}
// ๊ฒ์๊ธ ์ญ์ ์ฒ๋ฆฌ - /board/delete - [POST]
@PostMapping("/delete")
public String deletePro(int no) throws Exception {
int result = boardSerivce.delete(no);
logger.info("๊ฒ์๊ธ ์ญ์ ์์ฒญ - result : " + result);
return "redirect:/board/list";
}
}
Java
๋ณต์ฌ
๋ทฐ
board
โข
list.jsp
โข
read.jsp
โข
insert.jsp
โข
update.jsp
list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๊ฒ์๊ธ ๋ชฉ๋ก</title>
</head>
<body>
<h1>๊ฒ์๊ธ ๋ชฉ๋ก</h1>
<a href="${ pageContext.request.contextPath }/board/insert">๊ธ์ฐ๊ธฐ</a>
<table border="1">
<tr>
<th>๋ฒํธ</th>
<th>์ ๋ชฉ</th>
<th>์์ฑ์</th>
<th>๋ฑ๋ก์ผ์</th>
<th>์์ ์ผ์</th>
<th>์กฐํ์</th>
</tr>
<c:forEach items="${boardList}" var="board">
<tr>
<td align="center">${board.no}</td>
<td width="300">
<a href="${ pageContext.request.contextPath }/board/read?no=${board.no}">
${board.title}
</a>
</td>
<td align="center" width="120">${board.writer}</td>
<%-- <td align="center">${board.regDate}</td> --%>
<td align="center">
<fmt:formatDate value="${board.regDate}" pattern="yyyy-MM-dd HH:mm:ss"/>
</td>
<%-- <td align="center">${board.updDate}</td> --%>
<td align="center">
<fmt:formatDate value="${board.updDate}" pattern="yyyy-MM-dd HH:mm:ss"/>
</td>
<td align="center">${board.views}</td>
</tr>
</c:forEach>
</table>
</body>
</html>
HTML
๋ณต์ฌ
read.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๊ฒ์๊ธ ์กฐํ</title>
</head>
<body>
<h1>๊ฒ์๊ธ ์กฐํ</h1>
<form action="${ pageContext.request.contextPath }/board/delete" method="POST">
<input type="hidden" name="no" value="${board.no}" />
<table>
<tr>
<td><label for="title">์ ๋ชฉ</label></td>
<td><input type="text" name="title" value="${board.title}" /></td>
</tr>
<tr>
<td><label for="writer">์์ฑ์</label></td>
<td><input type="text" name="writer" value="${board.writer}" /></td>
</tr>
<tr>
<td><label for="content">๋ด์ฉ</label></td>
<td>
<textarea rows="5" cols="20" name="content" >${board.content}</textarea>
</td>
</tr>
</table>
<div>
<a href="${ pageContext.request.contextPath }/board/update?no=${board.no}">์์ </a>
<input type="submit" value="์ญ์ " />
</div>
</form>
</body>
</html>
HTML
๋ณต์ฌ
insert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๊ฒ์๊ธ ์ฐ๊ธฐ</title>
</head>
<body>
<h1>๊ฒ์๊ธ ์ฐ๊ธฐ</h1>
<form action="${ pageContext.request.contextPath }/board/insert" method="POST">
<table>
<tr>
<td><label for="title">์ ๋ชฉ</label></td>
<td><input type="text" name="title" /></td>
</tr>
<tr>
<td><label for="writer">์์ฑ์</label></td>
<td><input type="text" name="writer" /></td>
</tr>
<tr>
<td><label for="content">๋ด์ฉ</label></td>
<td>
<textarea rows="5" cols="20" name="content" ></textarea>
</td>
</tr>
</table>
<div>
<input type="submit" value="๋ฑ๋ก" />
</div>
</form>
</body>
</html>
HTML
๋ณต์ฌ
update.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>๊ฒ์๊ธ ์์ </title>
</head>
<body>
<h1>๊ฒ์๊ธ ์์ </h1>
<form action="${ pageContext.request.contextPath }/board/update" method="POST">
<input type="hidden" name="no" value="${board.no}" />
<table>
<tr>
<td><label for="title">์ ๋ชฉ</label></td>
<td><input type="text" name="title" value="${board.title}" /></td>
</tr>
<tr>
<td><label for="writer">์์ฑ์</label></td>
<td><input type="text" name="writer" value="${board.writer}" /></td>
</tr>
<tr>
<td><label for="content">๋ด์ฉ</label></td>
<td>
<textarea rows="5" cols="20" name="content" >${board.content}</textarea>
</td>
</tr>
</table>
<input type="submit" value="์์ " />
</form>
<form action="${ pageContext.request.contextPath }/board/delete" method="POST">
<input type="hidden" name="no" value="${board.no}" />
<input type="submit" value="์ญ์ " />
</form>
</body>
</html>
HTML
๋ณต์ฌ
Mybatis ํ๋ผ๋ฏธํฐ ๋งคํ ๋ฐฉ๋ฒ
๊ฐ์ฒด ๋งคํ
โข
Mapper ์ธํฐํ์ด์ค ์์ฑ ์ ๋งค๊ฐ๋ณ์๋ก DTO ๊ฐ์ฒด ์ฌ์ฉ: ๋งคํผ ์ธํฐํ์ด์ค์ ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก DTO ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ ํด๋น DTO ๊ฐ์ฒด์ ํ๋ ๊ฐ์ ์ฟผ๋ฆฌ์ ๋งคํํ ์ ์์ต๋๋ค.
public interface BoardMapper {
public List<Board> list(Board board);
}
Java
๋ณต์ฌ
โข
Mapper XML์์ #{} ์ฌ์ฉํ์ฌ ํ๋ ๊ฐ ๋งคํ: Mapper XML์์ #{}๋ฅผ ์ฌ์ฉํ์ฌ DTO ๊ฐ์ฒด์ ํ๋ ๊ฐ์ ๋งคํํ ์ ์์ต๋๋ค.
<select id="list" resultType="com.aloha.spring.dto.Board">
SELECT *
FROM board
WHERE title = #{title} AND writer = #{writer}
</select>
XML
๋ณต์ฌ
@Param ์ด๋ ธํ ์ด์ ์ฌ์ฉ
โข
Mapper ์ธํฐํ์ด์ค ์์ฑ ์ @Param ์ด๋
ธํ
์ด์
์ฌ์ฉ: ๋งคํผ ์ธํฐํ์ด์ค์ ๋ฉ์๋์ @Param ์ด๋
ธํ
์ด์
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฟผ๋ฆฌ์ ๋งคํํ ์ ์์ต๋๋ค.
public interface BoardMapper {
public int insert(@Param("title") String title
, @Param("writer") String writer
, @Param("content") String content);
}
Java
๋ณต์ฌ
โข
Mapper XML์์ ํ๋ผ๋ฏธํฐ ๋ช
์ผ๋ก ๋งคํ: Mapper XML์์ ํ๋ผ๋ฏธํฐ ๋ช
์ ์ฌ์ฉํ์ฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ฟผ๋ฆฌ์ ๋งคํํ ์ ์์ต๋๋ค.
<insert id="insert">
INSERT INTO board ( title, writer, content )
VALUES ( #{title}, #{writer}, #{content} )
</insert>
XML
๋ณต์ฌ
Map ์ปฌ๋ ์ ๋งคํ
โข
Mapper ์ธํฐํ์ด์ค ์์ฑ ์ Map ์ปฌ๋ ์
์ฌ์ฉ: ๋งคํผ ์ธํฐํ์ด์ค์ ๋ฉ์๋์ Map ์ปฌ๋ ์
์ ์ฌ์ฉํ์ฌ ์ฌ๋ฌ ๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฟผ๋ฆฌ์ ๋งคํํ ์ ์์ต๋๋ค.
public interface BoardMapper {
public int update(Map<String,String> map);
}
Java
๋ณต์ฌ
map
{
no : โ100โ,
title : โ์ ๋ชฉโ,
writer : โ์์ฑ์โ,
content : โ๋ด์ฉโ,
}
โข
Mapper XML์์ ํ๋ผ๋ฏธํฐ ๋ช
์ผ๋ก ๋งคํ: Mapper XML์์ ํ๋ผ๋ฏธํฐ ๋ช
์ ์ฌ์ฉํ์ฌ ๋งค๊ฐ๋ณ์๋ฅผ ์ฟผ๋ฆฌ์ ๋งคํํ ์ ์์ต๋๋ค.
<update id="update">
UPDATE board
SET title = #{title}
,writer = #{writer}
,content = #{content}
,upd_date = now()
WHERE no = #{no}
</update>
XML
๋ณต์ฌ
Mybatis SQL
select ๋ฌธ
MyBatis์ SELECT ๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๋ฐ์ดํฐ๋ฅผ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ง์ ๋ ์กฐ๊ฑด์ ๊ธฐ๋ฐํ์ฌ ๋จ์ผ ๋๋ ๋ค์ค ํ์ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. SELECT ๋ฌธ์ ๊ฒฐ๊ณผ๋ Java ๊ฐ์ฒด ๋๋ Java ๊ฐ์ฒด ์ปฌ๋ ์
์ ๋งคํ๋ ์ ์์ต๋๋ค.
<select id="select" resultType="com.aloha.spring.dto.Board">
SELECT *
FROM board
WHERE no = #{no}
</select>
XML
๋ณต์ฌ
์์ ์ฝ๋์์ select ๋ฌธ์ no ๋งค๊ฐ ๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก board ํ
์ด๋ธ์์ ๋จ์ผ ํ์ ๊ฒ์ํฉ๋๋ค. ๊ฒฐ๊ณผ๋ Board ํด๋์ค์ ๋งคํ๋ฉ๋๋ค.
insert ๋ฌธ
MyBatis์ INSERT ๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์๋ก์ด ๋ ์ฝ๋๋ฅผ ์ฝ์
ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ๋จ์ผ ํ ๋๋ ํ ๋ฒ์ ์ฌ๋ฌ ํ์ ์ฝ์
ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ฝ์
ํ ๊ฐ์ ๋งค๊ฐ ๋ณ์๋ก ์ ๊ณตํ๊ฑฐ๋ Java ๊ฐ์ฒด๋ก๋ถํฐ ๋งคํํ ์ ์์ต๋๋ค.
<insert id="insert">
INSERT INTO board (title, writer, content)
VALUES (#{title}, #{writer}, #{content})
</insert>
XML
๋ณต์ฌ
์์ ์ฝ๋์์ insert ๋ฌธ์ title, writer, ๋ฐ content ๋งค๊ฐ ๋ณ์์์ ์ ๊ณต๋ ๊ฐ์ผ๋ก board ํ
์ด๋ธ์ ์๋ก์ด ํ์ ์ฝ์
ํฉ๋๋ค.
update ๋ฌธ
MyBatis์ UPDATE ๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๊ธฐ์กด ๋ ์ฝ๋๋ฅผ ์์ ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ง์ ๋ ์กฐ๊ฑด์ ๊ธฐ๋ฐํ์ฌ ํ๋ ์ด์์ ์ด์ ์์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์์ ํ ๊ฐ์ ๋งค๊ฐ ๋ณ์๋ก ์ ๊ณตํ๊ฑฐ๋ Java ๊ฐ์ฒด๋ก๋ถํฐ ๋งคํํ ์ ์์ต๋๋ค.
<update id="update">
UPDATE board
SET title = #{title},
writer = #{writer},
content = #{content},
upd_date = now()
WHERE no = #{no}
</update>
XML
๋ณต์ฌ
์์ ์ฝ๋์์ update ๋ฌธ์ no ๋งค๊ฐ ๋ณ์๋ฅผ ๊ธฐ๋ฐ์ผ๋ก board ํ
์ด๋ธ์ title, writer, content, ๋ฐ upd_date ์ด์ ์์ ํฉ๋๋ค.
delete ๋ฌธ
MyBatis์ DELETE ๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ๊ธฐ์กด ๋ ์ฝ๋๋ฅผ ์ ๊ฑฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ง์ ๋ ์กฐ๊ฑด์ ๊ธฐ๋ฐํ์ฌ ํ๋ ์ด์์ ํ์ ์ญ์ ํ๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค.
<delete id="delete">
DELETE FROM board
WHERE no = #{no}
</delete>
XML
๋ณต์ฌ
selectKey ๋ฌธ
MyBatis์ SELECTKEY ๋ฌธ์ INSERT ๋ฌธ์์ ์์ฑ๋ ํค ๊ฐ์ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ฃผ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ๋ ์ฝ๋๋ฅผ ์ฝ์
ํ ํ ์๋์ผ๋ก ์์ฑ๋ ๊ธฐ๋ณธ ํค ๊ฐ์ ๊ฒ์ํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
<insert id="insert">
<selectKey resultType="java.lang.Integer" keyProperty="parentNo" order="BEFORE">
SELECT MAX( ${pk} ) FROM ${parentTable}
</selectKey>
INSERT INTO file (parent_table, parent_no, file_name, file_path)
VALUES (#{parentTable}, #{parentNo}, #{fileName}, #{filePath})
</insert>
XML
๋ณต์ฌ
์์ ์ฝ๋์์ selectKey ๋ฌธ์ ๋ง์ง๋ง์ผ๋ก ์ฝ์
๋ ID ๊ฐ์ ๊ฒ์ํ๊ณ Java ๊ฐ์ฒด์ no ์์ฑ์ ๋งคํํฉ๋๋ค. ์ด๋ฅผ ํตํด ์ ๋ ์ฝ๋๋ฅผ ์ฝ์
ํ ํ ์์ฑ๋ ํค ๊ฐ์ ์ก์ธ์คํ ์ ์์ต๋๋ค.
${ } vs #{ }
โข
${ } : ๋์ด์จ ๋งค๊ฐ๋ณ์์ ๊ฐ์, ๊ทธ๋๋ก ์ถ๋ ฅ
โข
#{ } : ๋์ด์จ ๋งค๊ฐ๋ณ์์ ๊ฐ์, ์๋ ํ์
๋ณํํ์ฌ ์ถ๋ ฅ
ํจ์ & ํ๋ก์์ ํธ์ถ
๋ง์ด๋ฐํฐ์ค์์ ํจ์๋ ํ๋ก์์ ๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์๋ ค๋๋ฆฌ๊ฒ ์ต๋๋ค.
ํจ์ ํธ์ถ: ํจ์๋ฅผ ํธ์ถํ๋ ค๋ฉด SELECT ๋ฌธ์ ์ฌ์ฉํ์ฌ ํจ์๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํด์ผ ํฉ๋๋ค. ์๋ ์์ ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
<select id="callFunction" resultType="java.lang.Integer" statementType="CALLABLE">
{ #{result, mode=OUT, jdbcType=INTEGER} = call functionName(#{param1, jdbcType=INTEGER}, #{param2, jdbcType=INTEGER}) }
</select>
XML
๋ณต์ฌ
์์ ์์ ์์๋ callFunction์ด๋ผ๋ SELECT ๋ฌธ์ ์ฌ์ฉํ์ฌ functionName์ด๋ผ๋ ํจ์๋ฅผ ํธ์ถํ๊ณ ๊ฒฐ๊ณผ ๊ฐ์ ๋ฐํํฉ๋๋ค. param1๊ณผ param2๋ ํจ์์ ์ ๋ฌ๋๋ ๋งค๊ฐ๋ณ์์ด๋ฉฐ, result๋ ํจ์์ ๊ฒฐ๊ณผ ๊ฐ์ ์ ์ฅํ๋ ๋ณ์์
๋๋ค.
1.
ํ๋ก์์ ํธ์ถ: ํ๋ก์์ ๋ฅผ ํธ์ถํ๋ ค๋ฉด INSERT, UPDATE ๋๋ DELETE ๋ฌธ์ ์ฌ์ฉํ์ฌ ํ๋ก์์ ๋ฅผ ์คํํด์ผ ํฉ๋๋ค. ์๋ ์์ ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
<insert id="callProcedure" statementType="CALLABLE">
{ call procedureName(#{param1, jdbcType=INTEGER}, #{param2, jdbcType=VARCHAR}) }
</insert>
XML
๋ณต์ฌ
์์ ์์ ์์๋ callProcedure์ด๋ผ๋ INSERT ๋ฌธ์ ์ฌ์ฉํ์ฌ procedureName์ด๋ผ๋ ํ๋ก์์ ๋ฅผ ํธ์ถํฉ๋๋ค. param1๊ณผ param2๋ ํ๋ก์์ ์ ์ ๋ฌ๋๋ ๋งค๊ฐ๋ณ์์
๋๋ค.
์์ ์์ ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ฌ ๋ง์ด๋ฐํฐ์ค์์ ํจ์๋ ํ๋ก์์ ๋ฅผ ํธ์ถํ๋ ๋ฐฉ๋ฒ์ ์ ์ฉํด๋ณด์ธ์.
MyBatis ๋์ SQL
MyBatis์์ ๋์ SQL์ ์์ฑํ๋ ๋ฐฉ๋ฒ์๋ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ต๋๋ค. ๋ค์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋์ SQL ๋ฌธ๋ฒ์ ๋ช ๊ฐ์ง ์์์
๋๋ค.
IF ๋ฌธ
<if test="condition">
<!-- ์กฐ๊ฑด์ด true์ผ ๋ ์คํ๋๋ SQL ๊ตฌ๋ฌธ -->
</if>
XML
๋ณต์ฌ
choose ๋ฌธ
โข
chooese
โฆ
when
โฆ
otherwise
<choose>
<when test="condition1">
<!-- condition1์ด true์ผ ๋ ์คํ๋๋ SQL ๊ตฌ๋ฌธ -->
</when>
<when test="condition2">
<!-- condition2๊ฐ true์ผ ๋ ์คํ๋๋ SQL ๊ตฌ๋ฌธ -->
</when>
<otherwise>
<!-- ์์ ๋ชจ๋ ์กฐ๊ฑด์ด false์ผ ๋ ์คํ๋๋ SQL ๊ตฌ๋ฌธ -->
</otherwise>
</choose>
XML
๋ณต์ฌ
foreach ๋ฌธ
<foreach collection="list" item="item" separator=",">
<!-- list์ ๋ชจ๋ ์์์ ๋ํด ์คํ๋๋ SQL ๊ตฌ๋ฌธ -->
</foreach>
XML
๋ณต์ฌ
TRIM ๋ฌธ
<!-- prefix์ suffix์๋ ํด๋น ๊ตฌ๋ฌธ์ ๋๋ฌ์ธ๋ ์ ๋์ฌ์ ์ ๋ฏธ์ฌ๊ฐ ์ฌ ์ ์์ผ๋ฉฐ, ์ ๋์ฌ ๋๋ ์ ๋ฏธ์ฌ๊ฐ ํ์ํ์ง ์์ ๊ฒฝ์ฐ ์๋ตํ ์ ์์ต๋๋ค. -->
<trim prefix="prefix" suffix="suffix" prefixOverrides="prefixOverrides" suffixOverrides="suffixOverrides">
<!-- prefixOverrides์ suffixOverrides๋ ์๋ต ๊ฐ๋ฅํ ์์๋ก, SQL ๊ตฌ๋ฌธ์ ์ ๋์ฌ ๋๋ ์ ๋ฏธ์ฌ๋ฅผ ์ ๊ฑฐํฉ๋๋ค. -->
<!-- SQL ๊ตฌ๋ฌธ -->
</trim>
XML
๋ณต์ฌ
set ๋ฌธ
๋์ SQL์ ์์ฑํ๊ธฐ ์ํด MyBatis์์ ์ ๊ณตํ๋ set ๋ฌธ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. set ๋ฌธ๋ฒ์ UPDATE ์ฟผ๋ฆฌ์์ ํ์ํ ํ๋๋ง ๋์ ์ผ๋ก ์
๋ฐ์ดํธํ ์ ์๋ ์ ์ฉํ ๊ธฐ๋ฅ์
๋๋ค. ๋ค์์ set ๋ฌธ๋ฒ์ ์์์
๋๋ค.
<update id="update">
UPDATE board
<set>
<if test="title != null">
title = #{title},
</if>
<if test="writer != null">
writer = #{writer},
</if>
<if test="content != null">
content = #{content},
</if>
</set>
WHERE no = #{no}
</update>
XML
๋ณต์ฌ
์์ ์์์์๋ title, writer, content ํ๋๊ฐ null์ด ์๋ ๊ฒฝ์ฐ์๋ง ํด๋น ํ๋๋ฅผ ์
๋ฐ์ดํธํ๋๋ก ์ค์ ๋์ด ์์ต๋๋ค. ์ด๋ฅผ ํตํด ํ์ํ ํ๋๋ง ๋์ ์ผ๋ก ์
๋ฐ์ดํธํ ์ ์์ต๋๋ค.