파게로그

[Persistence Framework] column mapping, parameters in Mapper 본문

콤퓨타 왕기초/Spring Boot

[Persistence Framework] column mapping, parameters in Mapper

파게 2021. 5. 10. 21:29

Column Mapping

DB에서의 실제 column name과 Java 어플리케이션에서의 필드 변수명이 다를 때 어떻게 할 수 있을까?

첫째로, DB의 column name을 바꿀 수 있다. column name과 필드 변수명이 일치하는 것이 권장되지만, DB를 수정하기 힘든 경우가 많다. 둘째로, 필드 변수명과 getter, setter의 메서드 이름, 그리고 View에서 속성명을 모두 변경할 수 있다. 하지만 이는 굉장히 비효율적인 방법이다. 이러한 경우를 위해서 MyBatis는 column mapping을 지원한다.

 

package com.ddoongi.springbootwebprj.dao;

import com.ddoongi.springbootwebprj.entity.Assignment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface AssignmentDao {

    @Result(property = "regDate", column = "reg_date")
    @Select("SELECT * FROM assignment")
    List<Assignment> getList();

    Assignment getAssignment(int id);

}

 

단일 column mapping에 대해서는 위와 같이 @Result annotation을 이용한다.

 

package com.ddoongi.springbootwebprj.dao;

import com.ddoongi.springbootwebprj.entity.Assignment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface AssignmentDao {

    @Results({
        @Result(property = "regDate", column = "reg_date")
    })
    @Select("SELECT * FROM assignment")
    List<Assignment> getList();

    Assignment getAssignment(int id);

}

 

복수 column mapping에 대해서는 위와 같이 @Results annotation을 이용한다.


Parameters in Mapper

Mapper에서 파라미터를 이용하게 되는 경우도 있다.

 

com.ddoongi.springbootwebprj.controller.student.AssignmentController

@GetMapping("/list")
public String list(Model model) {
    int page = 1;
    String field = "title";
    String query = "";

    List<Assignment> list = service.getList(page, field, query);
    
    model.addAttribute("list", list);
    
    return "/student/assignment/list";
}

 

이렇게 파라미터를 이용하도록 Controller를 고쳐주고, 이를 위해 AssignmentService, AssignmentServiceImpl의 메서드에서 정의된 파라미터 또한 변경해준다. 다만 AssignServiceImpl의 메서드 내부는 아래와 같은데, 생각할 점이 있다.

 

@Override
public List<Assignment> getList(int page, String field, String query) {
    List<Assignment> list = assignmentDao.getList();
    return list;
}

 

getList( )가 갖는 파라미터를 assignmentDao.getList( )에 바로 전달하는 것은 곤란하다. Service가 갖는 파라미터와 DAO가 갖는 파라미가 전부 일치하는 경우는 흔치 않기 때문이다. DAO가 SQL Mapper라는 점을 고려하면, SQL이 구현할 수 있는 형태에 따라서 파라미터가 다를 것이기 때문이다. 실제 SQL문을 고려하면 곧 Dao의 메서드가 갖는 파라미터는 int page, int size, String field, String query가 될 것이다(MySQL에서는 offset, size일 것이며, Oracle도 12c부터 MySQL과 유사하게 SQL문을 작성할 수 있다).

이를 고려하면 AssignmentDao에서 getList( ) 메서드의 정의는 아래와 같이 바뀌어야 하며, AssignmentServiceImpl에서 getList( )를 호출하는 부분은 아래와 같이 파라미터가 전달되어야 한다.

@Select annotation 내에서, #{ ... }는 값을, ${ ... }는 홑따옴표 없이 그대로 삽입할 때 사용한다. 그리고 문자열을 연결할 때 띄어쓰기에 주의하도록 한다.

 

// com.ddoongi.springwebprj.dao.AssignmentDao
// Dao의 메서드 재정의
@Mapper
public interface AssignmentDao {

    @Result(property = "regDate", column = "reg_date")
    @Select("SELECT * " +
            "FROM (SELECT ROWNUM rownumber, B.* FROM " +
            "(SELECT * FROM assignment WHERE ${field} LIKE '%${query}%' ORDER BY reg_date DESC) B) A " +
            "WHERE A.rownumber BETWEEN #{offset} + 1 AND #{offset} + #{size}"
    )
    List<Assignment> getList(int offset, int size, String field, String query);

    Assignment getAssignment(int id);

}

// com.ddoongi.springwebprj.service.AssignmentImpl
// Service에서 메서드 호출 시 파라미터 전달
    @Override
    public List<Assignment> getList(int page, String field, String query) {

        int size = 10;
        int offset = (page - 1) * size;

        List<Assignment> list = assignmentDao.getList(offset, size, field, query);
        return list;
    }
Comments