MyBatis
어노테이션을 이용한 매핑은 비교적 최근에 나온 방법으로, 기본적으론 xml을 이용한 매핑을 많이 사용한다.
mybatis 스키마에 Products테이블 추가
DROP TABLE IF EXISTS Products;
CREATE TABLE Products(
prod_id INT PRIMARY KEY AUTO_INCREMENT,
prod_name VARCHAR(255) NOT NULL,
prod_price INT NOT NULL
);
INSERT INTO Products (prod_name, prod_price) values ('베베숲 물티슈', 2700);
INSERT INTO Products (prod_name, prod_price) values ('여름 토퍼', 35180);
INSERT INTO Products (prod_name, prod_price) values ('페이크 삭스', 860);
INSERT INTO Products (prod_name, prod_price) values ('우산', 2900);
Product클래스 생성
- Product -
private Long prodId; // CamelCase 다른 단어끼리 합칠때 두번째 단어부턴 첫문자만 대문자사용
private String prodName;
private int prodPrice;
// 생성자(모든 필드변수) , 생성자(id만 제외, 생성용) , get/set메서드 자동완성
클래스를 DB에 있는 데이터를 받아올 때 사용
- application.properties -
# MySQL DB setting
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1234
# MyBatis
# mapper.xml 위치 지정
mybatis.mapper-locations: mapper/*.xml
# model 프로퍼티 camel case 설정
mybatis.configuration.map-underscore-to-camel-case=true
# 패키지 result tpye 을 생략할 수 있도록 alias 설정
mybatis.type-aliases-package=com.myapp.mybatis.model
# mapper 로그레벨 설정
logging.level.com.myapp.mybatis.mapper=TRACE
xml의 위치는 java코드가 아니므로 resources에 들어가게 됨.
resources의 mapper폴더를 만들어 거기에 저장되도록 설정함.
mybatis.configuration.map-underscore-to-camel-case=true
: 언더바를 camel case로 변환하는 설정.
DB는 대소문자 구별이 없으므로 언더바를 이용해 단어의 결합을 구분, java는 대소문자를 구분하므로 camel case방식을 사용함.
이렇게 될 경우 서로 이름이 다르게 되는데 이를 같은 이름으로 인식하여 매핑되도록 변환하는 설정임.
mybatis.type-aliases-package=com.myapp.mybatis.model
: 저장될 패키지의 이름을 생략할 수 있도록 미리 설정해줌
logging.level.com.myapp.mybatis.mapper=TRACE
: MyBatis의 로그레벨을 TRACE로 설정하여 기본설정인 info보다 자세히 나오도록 설정.
새 클래스 생성
- ProductMapper -
@Mapper
public interface ProductMapper {
// 구현이 안된 추상메서드들을 연결된 mapper폴더의 ProductMapper.xml에서 작성함.
Product selectProductById(Long id); // id로 제품검색
List<Product> selectAllProducts(); // 모든 제품 리스트
void insertProduct(Product product); // 새 제품 생성
void updateProduct(Product product); // 제품 수정
void deleteProductById(Long id); // id로 제품 삭제
}
xml파일을 생성해 매핑
resources의 mapper폴더에 ProductMapper.xml 생성
MyBatis github 을 참고하여 기본내용 붙여넣기
- ProductMapper.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="com.myapp.mybatis.mapper.ProductMapper">
<select id="selectProductById" resultType="com.myapp.mybatis.model.Product">
SELECT prod_id
,prod_name
,prod_price
FROM products
WHERE prod_id = #{prodId}
</select>
<select id="selectAllProducts" resultType="Product">
SELECT prod_id
,prod_name
,prod_price
FROM products
</select>
<insert id="insertProduct" parameterType="Product">
INSERT INTO products (prod_name, prod_price)
VALUES (#{prodName}, #{prodPrice})
</insert>
</mapper>
태그 내에 sql을 입력하면 됨. jpa에서 지원하지 않는 복잡한 sql문도 가능.
(사용자로부터 입력받는)변수를 사용 시 #{변수명}
의 형태로 사용.
<mapper namespace="com.myapp.mybatis.mapper.ProductMapper">
: 현재 사용하고있는 프로젝트의 폴더명에 따라 변경한다.
resultType="Product"
: 원래는 위치를 작성할때 resultType="com.myapp.mybatis.model.Product"
처럼 처음부터 모두 적어야하지만 위에서 application.properties에 설정을 해뒀으므로 Product만 써도 됨.
id="selectProductById"
: 앞서 ProductMapper인터페이스에서 선언만 하고 구현하지 않은 필드명과 이름을 같게 맞춤.
컨트롤러 패키지에 User컨트롤러와 같이 ProductCotroller클래스 생성
- ProductController -
@RestController
@RequestMapping("/products")
public class ProductController {
private ProductMapper productMapper;
//생성자 주입 (객체를 생성자 주입으로 입력시 @Autowired 필요없음, 권장 )
public ProductController(ProductMapper productMapper) {
this.productMapper = productMapper;
}
@GetMapping("/{id}")
public Product getProduct(@PathVariable("id") Long id) {
Product product = productMapper.selectProductById(id);
return product;
}
@GetMapping
public List<Product> getProductList(){
List<Product> productList = productMapper.selectAllProducts();
return productList;
}
@PostMapping //파라메터 prodName, prodPrice
public void creatProduct(@RequestParam("name") String prodName,
@RequestParam("price") int prodPrice ) {
productMapper.insertProduct(new Product(prodName, prodPrice));
}
@PutMapping("/{id}")
public void editProduct(@PathVariable("id") Long id,
@RequestParam("name") String prodName,
@RequestParam("price") int prodPrice ) {
productMapper.updateProduct(new Product(id, prodName, prodPrice));
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable("id") Long id) {
productMapper.deleteProductById(id);
}
}
객체를 주입하는 방법으로 필드 주입(DI)과 생성자 주입이 있음.
postman을 이용해 확인
http://localhost:8080/products
http://localhost:8080/products?name=삼성노트북&price=700000
=> 일단 안돼서 넘어감.
앞서만든 mybatis 스키마에 board테이블 생성
DROP TABLE IF EXISTS board;
create table board(
bno int auto_increment primary key,
title varchar(150) not null,
content varchar(2000) not null,
writer varchar(50) not null,
regdate timestamp default now() not null,
updatedate timestamp default now() not null
);
insert into board(title, content, writer) values ('테스트 제목1', '테스트 내용1', '작가1');
insert into board(title, content, writer) values ('테스트 제목2', '테스트 내용2', '작가2');
insert into board(title, content, writer) values ('테스트 제목3', '테스트 내용3', '작가3');
차례로 게시글 번호, 글제목, 내용, 작성자, 등록날짜, 수정날짜
regdate
와 updatedate
는 입력을 하지 않으면 now()
에 의해 현재시간과 날짜가 기본값으로 입력됨.
테스트데이터를 입력하여 확인.
입력 시 title
, content
, writer
만 입력해도 regdate
와 updatedate
는 default값이 입력됨.
새 프로젝트 bbs생성
- application.properties -
# DB setting
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=1234
MySQL DB설정. 이 설정을 안하고 실행 시 에러발생.