Search

Mybatis

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
β—¦
νŒ¨ν‚€μ§€ ꡬ성 : μ΅œμƒμœ„ νŒ¨ν‚€μ§€(top level package)의 mapper νŒ¨ν‚€μ§€μ™€ 일치
β—¦
~/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 μ–΄λ…Έν…Œμ΄μ…˜μ„ μ •μ˜ν•œλ‹€.
λ©”μ†Œλ“œ λͺ…은 Mapper.xml 맀핑 파일의 μΏΌλ¦¬νƒœκ·Έ id κ°’κ³Ό μΌμΉ˜ν•΄μ•Όν•œλ‹€.
@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이 μ•„λ‹Œ κ²½μš°μ—λ§Œ ν•΄λ‹Ή ν•„λ“œλ₯Ό μ—…λ°μ΄νŠΈν•˜λ„λ‘ μ„€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό 톡해 ν•„μš”ν•œ ν•„λ“œλ§Œ λ™μ μœΌλ‘œ μ—…λ°μ΄νŠΈν•  수 μžˆμŠ΅λ‹ˆλ‹€.