임도현의 성장
Spring-Boot MyBatis 본문
📌 MyBatis
Mybatis는 데이터베이스로부터 직접 SQL문으로 데이터를 가져오고 객체(Entity든지, DTO든지, VO든지)에 반영하여 사용하도록 해주는 데이터베이스 접근 프레임워크이다. MyBatis의 가장 매력적인 점은 SQL을 XML에 편리하게 작성할 수 있고 또 "동적 쿼리"를 매우 편리하게 작성할 수 있다는 점이다.
📒의존성 주입
build.gradle에 다음 의존 관계를 추가한다.
//MyBatis 추가
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
📒 properties 설정
- mybatis.type-aliases-package : 마이바티스에서 "타입 정보"를 사용할 때는 패키지 이름을 적어주어야 하는데, 여기에 명시하면 패키지 이름 을 생략할 수 있다. 여러 위치를 지정하려면 , ; 로 구분하면 된다.
- mybatis.configuration.map-underscore-to-camel-case : 언더바를 카멜로 자동 변경해주는 기능을 활성 화 한다.
- logging.level.hello.itemservice.repository.mybatis=trace : MyBatis에서 실행되는 쿼리 로그를 확인할 수 있다.
mybatis.type-aliases-package=hello.itemservice.domain
mybatis.configuration.map-underscore-to-camel-case=true
logging.level.hello.itemservice.repository.mybatis=trace
👻 Vo 객체 생성
@Data
public class Item {
private Long id;
private String itemName;
private Integer price;
private Integer quantity;
public Item() {
}
public Item(String itemName, Integer price, Integer quantity) {
this.itemName = itemName;
this.price = price;
this.quantity = quantity;
}
}
🤯 DTO 구현
- DTO : 데이터 전송 객체
- DTO는 기능은 없고 데이터를 전달만 하는 용도로 사용되는 객체를 뜻한다.
- 객체 이름에 DTO를 붙혀 구분을 하지만 나는 Cond라는 검색 용도로 작성하였다.
@Data
public class ItemSearchCond {
private String itemName;
private Integer maxPrice;
public ItemSearchCond() {
}
public ItemSearchCond(String itemName, Integer maxPrice) {
this.itemName = itemName;
this.maxPrice = maxPrice;
}
}
🤔 Controller 구현
@Slf4j
@Controller
@RequestMapping("/items")
@RequiredArgsConstructor
public class ItemController {
private final ItemService itemService;
@GetMapping // 아이템, 검색 아이템 보여주는 메서드
public String items(@ModelAttribute("itemSearch") ItemSearchCond itemSearch, Model model) {
List<Item> items = itemService.findItems(itemSearch);
model.addAttribute("items", items);
return "items";
}
@GetMapping("/add") // 아이템 등록 폼 메서드
public String addForm() {
return "addForm";
}
@PostMapping("/add") // 아이템 등록 메서드
public String addItem(@ModelAttribute Item item, RedirectAttributes redirectAttributes) {
Item savedItem = itemService.save(item);
redirectAttributes.addAttribute("itemId", savedItem.getId());
redirectAttributes.addAttribute("status", true);
return "redirect:/items/{itemId}";
}
}
🙊 Service 클래스
- RequiredArgsConstructor : 자동 생성자 주입
- Autowired : 생성자 주입
@Service
@RequiredArgsConstructor
public class ItemService {
// @Autowired
// private ItemMapper itemMapper;
private final ItemMapper itemMapper;
// 아이템, 검색 아이템 보여주는 메서드
public List<Item> findItems(ItemSearchCond itemSearch){
return itemMapper.findAll(itemSearch);
}
// 아이템 등록 메서드
public Item save(Item item) {
itemMapper.save(item);
return item;
}
}
💩 Mapper 인터페이스 생성
- @Mapper 애노테이션을 붙여주어야 MyBatis에서 인식할 수 있다.
- 인터페이스의 메서드를 호출하면 다음에 보이는 xml 의 해당 SQL을 실행하고 결과를 돌려준다.
@Mapper
public interface ItemMapper {
List<Item> findAll(ItemSearchCond itemSearch); // 아이템, 검색 아이템 보여주는 메서드
void save(Item item); // 아이템 등록 메서드
}
💩 XML 파일 생성
- XML 파일은 자바 코드가 아니기 때문에 src/main/resources 하위에 만들되, 패키지 위치는 맞추어 주어야 한다.
- namespace : Mapper Interface 경로를 지정하면 된다.
<?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="hello.itemservice.repository.mybatis.ItemMapper">
<select id="findAll" resultType="Item">
select id, item_name, price, quantity
from item
<where>
<if test="itemName != null and itemName != ''">
and item_name like concat('%',#{itemName},'%')
</if>
<if test="maxPrice != null">
and price <= #{maxPrice}
</if>
</where>
</select>
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into item (item_name, price, quantity)
values (#{itemName}, #{price}, #{quantity})
</insert>
</mapper>
- Mybatis는 <where> , <if> 같은 동적 쿼리 문법을 통해 편리한 동적 쿼리를 지원한다.
- <if>가 모두 실패하게 되면 SQL where 를 만들지 않는다.
- <if>가 하나라도 성공하면 처음 나타나는 and를 where로 변환해준다.
// if가 모두 실패하면
select id, item_name, price, quantity
from item
// 하나라도 성공하면
select id, item_name, price, quantity
from item
where item_name like concat('%',#{itemName},'%')
🌐 XML 파일 경로
Mapper가 있는 패키지 위치를 맞추어 주었다.
XML 파일을 원하는 위치에 두고 싶으면 application.properties 에 다음과 같이 설정하면 된다.
mybatis.mapper-locations=classpath:mapper/**/*.xml 이렇게 하면 resources/mapper 를 포함한 그 하위 폴더에 있는 XML을 XML 매핑 파일로 인식한다. 이 경우 파일 이름은 자유롭게 설정해도 된다.
🐧구조를 설명하자면🐧
방향 Controler 👉 Service 👉 Mapper
- Controler 는 웹 브라우저의 요청을 전담하여 처리 후 Service를 호출
- Service 는 비즈니스 로직을 수행 후 데이터 베이스에 접근하는 Mapper를 이용해 결과 값을 받아 옵니다.
- Mapper 는 데이터베이스에 접속하여 비즈니스로 로직 실행에 필요한 쿼리를 호출합니다.
참고 자료
스프링 DB 2편 - 데이터 접근 활용 기술
'Spring Boot' 카테고리의 다른 글
Spring Data JPA + Query Dsl JPA (2) | 2024.09.07 |
---|---|
Spring-Boot H2 데이터베이스 설정과 연결 (1) | 2024.09.02 |
Spring-Boot Cookie Session (1) | 2024.08.13 |
Spring-Boot Interceptor (36) | 2024.07.26 |
Spring-Boot Bean validationn (0) | 2024.07.25 |