Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

임도현의 성장

Spring-Boot MyBatis 본문

Spring Boot

Spring-Boot MyBatis

림도현 2024. 9. 1. 17:30

📌 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 &lt;= #{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 
  1. Controler 는 웹 브라우저의 요청을 전담하여 처리 후 Service를 호출
  2. Service 는 비즈니스 로직을 수행 후 데이터 베이스에 접근하는 Mapper를 이용해 결과 값을 받아 옵니다.
  3. 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