포스트

MyBatis 결과 매핑 에러 해결2

Mybatis 사용중, 쿼리 결과가 dto 에 제대로 매핑이 안되는 오류가 발생했다2

이번에도 mismatch 에러다.

Error instantiating class com.example.springboard.domain.boards.Board with invalid types (int,String,BoardAccessAuthority) or values (1,all_board,1).
Cause: java.lang.IllegalArgumentException: argument type mismatch

Board 객체를 가져올 때, Board 객체의 필드인 AccessAuthority 를 join 해서 가져오도록 하는 과정에서 발생한 에러이다.
코드는 다음과 같다.

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.example.springboard.domain.boards;

import com.example.springboard.domain.BaseEntity;

public class Board extends BaseEntity {

  private int id;
  private String title;
  private BoardAccessAuthority boardAccessAuthority;

  public Board(int id, String title, BoardAccessAuthority boardAccessAuthority) {
    this.id = id;
    this.title = title;
    this.boardAccessAuthority = boardAccessAuthority;
  }

  static Board of(int id, String title, BoardAccessAuthority boardAccessAuthority) {
    return new Board(id, title, boardAccessAuthority);
  }

  public int getId() {
    return id;
  }

  public String getTitle() {
    return title;
  }

  public BoardAccessAuthority getBoardAccessAuthority() {
    return boardAccessAuthority;
  }

  public void setId(int id) {
    this.id = id;
  }

  public void setTitle(String title) {
    this.title = title;
  }

  public void setBoardAccessAuthority(
    BoardAccessAuthority boardAccessAuthority) {
    this.boardAccessAuthority = boardAccessAuthority;
  }
}


public class BoardAccessAuthority {

  private int id;
  private String accessLevel;

  public BoardAccessAuthority(int id, String accessLevel) {
    this.id = id;
    this.accessLevel = accessLevel;
  }

  static BoardAccessAuthority of(int id, String accessLevel) {
    return new BoardAccessAuthority(id, accessLevel);
  }

  public int getId() {
    return id;
  }

  public String getAccessLevel() {
    return accessLevel;
  }

  public void setAccessLevel(String accessLevel) {
    this.accessLevel = accessLevel;
  }

  public void setId(int id) {
    this.id = id;
  }
}

Mapper xml 을 다음과 같이 구성됐다.

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
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springboard.mapper.BoardMapper">

  <resultMap id="boardAccessAuthorityResultMap"
    type="com.example.springboard.domain.boards.BoardAccessAuthority">
    <result column="board_access_authority_id" property="id"/>
    <result column="access_level" property="accessLevel"/>
  </resultMap>

  <resultMap id="boardResultMap" type="com.example.springboard.domain.boards.Board">
    <result column="title" property="title"/>
    <result column="id" property="id"/>
    <collection property="boardAccessAuthority" resultMap="boardAccessAuthorityResultMap"/>
  </resultMap>

  <select id="findAll" resultMap="boardResultMap">
    SELECT a.id,
    a.title,
    b.id as board_access_authority_id,
    b.access_level
    FROM boards a
    INNER JOIN board_access_authorities b ON a.access_authority_id = b.id
  </select>

</mapper>

클래스와 매퍼의 코드에는 문제가 없어보이는데 왜 board 를 찾은 결과가 제대로 dto 에 매핑이 되지 않는걸까

원인은 간단했다. 기본 생성자가 없었기 때문이다.
앞선 글에서 살펴봤듯이, 기본 생성자가 없다면 제대로 객체의 생성이 이루어지지 않는다.

혹시라도 join 을 이용해 연관 관계에 있는 객체를 eager fetch 하는 경우 나같은 문제를 겪는 사람은 생성자를 다시 살펴보기 바란다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.