본문 바로가기
Development/Spring Boot

스프링부트 MyBatis에서 파라미터 여러개 넘기기 (parameterType)

by Nahwasa 2022. 2. 18.

 

  사실 Map 형태로 되어있는 프로젝트라면 모든 Map들을 합쳐서 보내면 되니 별 문제가 없다. 내 경우엔 사용자로 부터 컨트롤러로 들어오는 dto가 여러 종류일 때, 그 종류와 상관없이 동일한 형태로(각 dto에 상응하는 entity를 하나씩 만들고 싶지 않았다) MyBatis에 보내고 싶었다. 또한 해당 요청의 uri도 자동으로 넣어졌으면 좋겠고, JWT+스프링 시큐리티로 AuthenticationPrincipal에 넣어둔 인증된 사용자의 id가 있는 UserInfo도 자동으로 들어가게 하고 싶었다.

 

  즉, 여러 uri를 가지는 컨트롤러들어 있고 각 컨트롤러마다 사용자로부터 받는 dto 클래스가 다르다. 이 때 유저정보, uri, dto를 한꺼번에 물고 MyBatis에 보내고 싶었다. 그래서 다음과 같이 짜봤는데, 내가 원하는 기능은 모두 하므로 일단 개인 기록용으로 올려둔다. 현재로썬 따로 다른 자료들을 찾아보고 짠게 아니라서 분명 더 좋은 방법이 있을 것 같다. 차후 더 좋은 방법이 생기거나, 이게 안티패턴이라던가 이렇게 하면 안된다거나 하면 재작성하겠다.

 

  더 좋은 방법 있으면 댓글로 알려주세요.

 

 

1. @RestController - Controller 부분

@PostMapping("/notice")
public ResponseEntity<?> addNotice(
        HttpServletRequest req, 
        @AuthenticationPrincipal UserInfo userInfo, 
        @RequestBody NoticeAddDTO dto) {
    try {
        servicePlatformDbMapper.insertNotice(
                BaseEntity.<NoticeAddDTO>builder()
                        .data(dto)
                        .user(userInfo)
                        .from(req.getRequestURI())
                        .build()
        );
        return ResponseEntity.ok().build();
    } catch (Exception e) {
        return getErrorResponseEntity(e);
    }
}

  제너릭 타입의 BaseEntity를 통해 사용자로 부터 들어온 어떠한 타입의 dto라도 넣을 수 있게 했다. 그리고 JWT+스프링 시큐리티를 통해 SecurityContextHolder에 등록해둔 UserInfo (그냥 userId와 역할을 넣어두도록 한 클래스임. String userId, HashSet<> roles 만 있음)도 바로 넣어주고, uri는 HttpServletRequest에서 얻어온다. 이 경우 따로 하드코딩한 부분이 없으므로 휴먼에러를 줄일 수 있을 것이다.

 

  참고로 컨트롤러에서 이렇게 바로 처리하는 것 보다는 별도로 서비스로 빼는게 더 좋은 방식이다.

 

 

2. BaseEntity

@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class BaseEntity<T> {
    private T data;
    private UserInfo user;
    private String from;
}

  다양한 dto에 대응하기 위해 제너릭 타입을 사용한 entity이다. dto와 다른 부가 정보들을 감싸서 MyBatis로 보내기 위한 용도이다.

 

 

3. @Mapper - interface 부분

public void insertNotice(BaseEntity<NoticeAddDTO> dto) throws Exception;

 

 

4. MyBatis - xml 부분

<insert id="insertNotice" parameterType="com.nahwasa.xx.backend.entity.BaseEntity">
    INSERT INTO SP_NOTICE_MT (PLATFORM_CD, TITLE, CONTENTS, REG_DATE, REG_USER_ID, REG_FROM, MOD_DATE, MOD_USER_ID, MOD_FROM)
    VALUES (
            'XX',
            #{data.title},
            #{data.contents},
            NOW(),
            #{user.userId},
            #{from},
            NOW(),
            #{user.userId},
            #{from}
           )
</insert>

  다음과 같이 data.[~] 의 형태로 dto의 데이터를 사용할 수 있다. 이 경우 parameterType으로 BaseEntity만 기입하면 된다.

댓글