이번 시간에는 MyBatis-Spring-Boot-Starter 의 사용법에 대해 알아보겠습니다. MyBatis-Spring-Boot-Starter(http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/)를 참고했습니다. 다른 참고 문헌은 페이지 하단에 소개되어있습니다.
바쁘신 분들은 <mybatis-spring-boot-autoconfigure 간략 설명 > 부터 참고하세요.
사용 라이브러리
- lombok
- org.mybatis.spring.boot
- mybatis
- spring-boot
- mysql
MyBatis란?
마이바티스는 개발자가 지정한 SQL , 저장 프로시저, 그리고 몇 가지 고급 매핑을 지원하는 퍼시스턴스 프레임워크입니다. 마이바이트는 JDBC 로 처리하는 상당 부분의 코드와 파라미터 설정, 결과 매핑을 대신해줍니다.
- 저장 프로시저란, 일련의 쿼리를 하나의 함수처럼 실행하기 위한 쿼리의 집합이다.(위키백과)
- 퍼시스턴스 프레임워크: 데이터의 CRUD 를 다루는 클래스 및 설정 파일들의 집합이다. 사용시, JDBC 프로그래밍의 복잡함이나 번거로움 없이 간단한 작업으로 데이터베이스와 연동되는 시스템을 빠르게 개발할 수 있다.(위키 백과)
MyBatis-Spring 은 무엇일까?
마이바티스 스프링 연동모듈은 마이바티스와 스프링을 편하고 간단하게 연동한다.
MyBatis-Spring 의 효과
- 마이바티스가 스프링 트랜잭션에 쉽게 연동되도록 처리한다.
- 마이바티스 매퍼와
SqlSession
을 다루고 다른 빈에 주입시켜준다. - 마이바티스 예외를 스프링의
DataAccessException
로 변환한다. - 마이바티스, 스프링 또는 마이바티스 스프링 연동모듈에 의존성을 없앤다.
MyBatis 를 Spring 과 함께 사용하기 위한 필수 요소
SqlSessionFactory
- Mysql 서버와 MyBatis를 연결해주는건
SqlSessionFactory
객체이다. 데이터베이스와의 연결과 SQL의 실행에 대한 모든 것을 가지고있다. - 이 객체가
DataSource
를 참조하여 MyBatis와 Mysql 서버를 연동시켜준다. SqlSessionFactory
는DataSource
를 필요로 한다. 어떤DataSource
도 상관없지만 다른 스프링의 데이터베이스 연결과 동일하게 설정되어야 한다.
매퍼(Mapper)
- Mybatis 매핑(어노테이션 혹은 xml 파일)에 기재된 SQL을 호출하기 위한 인터페이스이다.
- 매퍼는 반드시 구현체 클래스가 아닌 인터페이스로 정의되어야 한다.
- 한번만 설정하면, 다른 스프링 빈에 주입하는 같은 방법으로 비즈니스/서비스 객체에 매퍼를 직접 주입할 수 있다.
- 실행중인 스프링 트랜잭션이 있다면, 트랜잭션이 완료되는 시점에 커밋이나 롤백이 될 것이다. 마지막으로 예외가 발생하면 스프링의
DataAccessException
예외가 발생한다.
mybatis-spring-boot-autoconfigure 간략 설명
MyBatis-Spring-Boot-Starter를 사용하면 스프링부트 위에 MyBatis 애플리케이션을 빠르게 빌드 할 수 있습니다 .
MyBatis-Spring-Boot-Starter 효과
즉
@Mapper
생성외의 다른 필수 작업들 ( 기존에 사용자가 설정해줘야 했던SqlSessionFactory
등등.. ) 을 자동으로 해줍니다.우리는 간단한 설정만 하면, 코 풀고
@Mapper
만 쓰면서 룰루랄라 mybatis 를 쓸 수 있습니다.
-
DataSource
를 자동 감지합니다. -
SqlSessionFactory
를 전달 하는 인스턴스를 자동 생성하고 등록합니다 -
DataSource
.SqlSessionFactoryBean
의 인스턴스를 만들고 등록합니다. -
@Mapper
주석이 표시된 매퍼를 자동 스캔하고에 연결합니다. -
SqlSessionTemplateSpring
컨텍스트에 등록하여 Bean에 주입 할 수 있도록합니다.
메이븐 설정
코드는 (http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/) 를 참고했습니다.
-
pom.xml
<dependency> <groupId> org.mybatis.spring.boot </ groupId> <artifactId> mybatis-spring-boot-starter </ artifactId> <version> 2.1.3 </ version> </dependency>
구성
application.properties
(또는 application.yml
) 안에 저장됩니다.
그 외의 구체적인 사항은 http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/ 를 참고하면 됩니다.
예제
dependency (maven)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com</groupId>
<artifactId>giftclub</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>giftclub</name>
<description>GiftClub project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
mysql 세팅
mybatis 에서 사용할 데이터베이스(giftclub
)와 테이블을 생성해줍니다. ( 사용한 sql 문은 따로 저장해두는 것이 좋습니다. )
drop table IF EXISTS shop;
create table shop(
id INTEGER AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128),
description VARCHAR(128),
INDEX (name)
);
drop table IF EXISTS product;
create table product(
id INTEGER AUTO_INCREMENT PRIMARY KEY,
shop_id INTEGER ,
name VARCHAR(128),
price INTEGER,
discount INTEGER,
description VARCHAR(128),
INDEX (name),
FOREIGN KEY(shop_id)REFERENCES shop(id)
);
환경 설정
application.properties
에 내가 사용할 데이터베이스 세팅을 해줍니다.
server.port=8080
server.servlet.context-path=/
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/[데이터베이스명]?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul
spring.datasource.username=[데이터베이스아이디]
spring.datasource.password=[데이터베이스비밀번호]
logging.level.com.giftclub=TRACE
logging.level.com.giftclub=TRACE
: 디비 쿼리를 로깅해주는 설정로깅을 패키지 단위로 나오게 한다. 약한 버전 DEBUG ( 리턴 버전 o : TRACE, x: DEBUG)
server.port=8080
: 8080포트를 이용합니다.
data 설정
내가 사용하는 데이터를 설정해 줍니다.
- lombok 의
@Data
어노테이션을 이용해 getter와 setter 를 자동 생성합니다.
package com.giftclub.shop;
import com.giftclub.product.Product;
import lombok.Data;
import java.util.List;
@Data
public class Shop {
private int id;
private String name;
private String description;
private List<Product> productList;
}
package com.giftclub.product;
import lombok.Data;
@Data
public class Product {
private int id;
private int shopId;
private String name;
private String description;
private int price;
private int discount;
}
mapper 생성
- mapper interface 를 생성합니다.
@Mapper
어노테이션을 이용하면, mapper 로 지정이 됩니다. - 어노테이션들에 대한 자세한 설명은 https://mybatis.org/mybatis-3/ja/apidocs/org/apache/ibatis/annotations/Results.html 로 가면 됩니다.
- sql 쿼리를 의미하는 어노테이션들:
@Insert
,@Select
,@Update
,@Delete
@Options(useGeneratedKeys = true, keyProperty = "id")
: 생성된 키를 가지고, "id" 에 대한 property 를 주는 역할을 수행한다.@Param
: sql 문의 변수로 들어간다.@Results
: result 를 표기하기 위한 방법을 표기한다.- 필드명 수정 :
@Result(property = "name", column = "user_name")
: DB의 user_name 을 name으로 수정해 표현 - 아이디 지정:
@ResultMap("CompanyMap")
형태로 후에 재사용 가능하다. - nested query: 추가로 외래키의 항목을 불러올 수 있다.
@Result(property = "productList", column = "id", many = @Many(select = "com.giftclub.product.ProductMapper.getByShopId"))
@Result(property = "id", column = "id", id = true),
nested query에서 사용한 필드값이 표시되게 한다.
- 필드명 수정 :
package com.giftclub.shop;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface ShopMapper {
final String getAll = "SELECT * FROM shop";
final String getById = "SELECT * FROM shop WHERE id=#{id}";
final String deleteById = "DELETE from shop WHERE id= #{id}";
final String insert = "INSERT INTO shop(name, description) VALUES(#{shop.name}, #{shop.description})";
final String update = "UPDATE shop SET name = #{shop.name}, description = #{shop.description} WHERE id= #{shop.id}";
@Insert(insert)
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(@Param("shop") Shop shop);
@Select("SELECT * FROM shop")
@Results(id = "shopMapper", value = {
@Result(property = "id", column = "id", id = true),
@Result(property = "productList", column = "id", many = @Many(select = "com.giftclub.product.ProductMapper.getByShopId")),
})
List<Shop> getAll();
@Select(getById)
@ResultMap("shopMapper")
Shop getById(@Param("id") int id);
@Update(update)
int update(@Param("shop") Shop shop);
@Delete(deleteById)
void deleteById(@Param("id") int id);
}
package com.giftclub.product;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface ProductMapper {
final String insert = "INSERT INTO product(name,shop_id, description,discount,price) VALUES(#{product.name},#{product.shopId}, #{product.description},#{product.discount},#{product.price})";
final String select = "SELECT * FROM product";
final String getById = "SELECT * FROM product WHERE id=#{id}";
final String getByShopId = "SELECT * FROM product WHERE shop_id=#{shopId}";
@Insert(insert)
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(@Param("product") Product product);
@Select(select)
@Results(id = "productMap",
value = {@Result(property = "shopId", column = "shop_id")})
List<Product> getAll();
@Select(getById)
@ResultMap("productMap")
Product getById(@Param("id") int id);
@Select(getByShopId)
@ResultMap("productMap")
List<Product> getByShopId(@Param("shopId") int shopId);
}
Controller 설정
package com.giftclub.user;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private UserMapper userMapper;
@PostMapping("")
public User post(@RequestBody User user) {
userMapper.insert(user);
return user;
}
@GetMapping("")
public List<User> getAll() {
return userMapper.getAll();
}
@GetMapping("/{id}")
public User getById(@PathVariable("id") int id) {
return userMapper.getById(id);
}
}
package com.giftclub.product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping(value = "/product")
public class ProductController {
@Autowired
private ProductMapper productMapper;
@PostMapping("")
public Product post(@RequestBody Product product) {
productMapper.insert(product);
return product;
}
@GetMapping("")
public List<Product> getAll() {
return productMapper.getAll();
}
@GetMapping("/{id}")
public Product getById(@PathVariable("id") int id) {
return productMapper.getById(id);
}
}
참고 문헌
-
https://linked2ev.github.io/mybatis/2019/09/08/MyBatis-5-MapperScan를-통한-Mapper-주입-방식/
-
http://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
-
https://arincblossom.wordpress.com/2018/05/15/mybatis-annotation/
-
https://www.tutorialspoint.com/mybatis/mybatis_annotations.htm ( mybatis annotation 설명 )
-
https://mybatis.org/mybatis-3/ja/apidocs/org/apache/ibatis/annotations/Results.html (nested query mybatis)
'프로젝트 - gift-shop' 카테고리의 다른 글
스프링 부트로 로그인 황금 코드✨ 만들기 (0) | 2021.03.15 |
---|---|
Stateful vs Stateless (0) | 2021.03.09 |
서버 2개 이상 세션 불일치 해결하기 (0) | 2021.03.09 |
서버 확장 전략 세우기: scale up vs scale out (0) | 2021.03.03 |
mvnw 의 필요성 (0) | 2021.02.28 |