에러 코드
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error querying database.
Cause: java.lang.IndexOutOfBoundsException: Index 4 out of bounds for length 4
### The error may exist in com/example/demo2/mapper/SiteUserMapper.java (best guess)
### The error may involve com.example.demo2.mapper.SiteUserMapper.getAllUser
### The error occurred while handling results ### SQL: select * from SiteUser
### Cause: java.lang.IndexOutOfBoundsException: Index 4 out of bounds for length 4
Mapper 인터페이스를 이용하여 모든 유저의 정보를 가져오는 코드를 작성했는데 위와 같은 에러 코드가 발생하였다. 아무리 생각해도 IndexOutOfBoundsException이 나올 수 없는 구조인데 이상하여 domain 객체를 확인해보았다.
문제의 원인
문제의 원인은 @Builder와 @Data 어노테이션에 있었다.
@Data
@Builder
public class SiteUser implements UserDetails {
private Long id;
private String email;
private String password;
private String username;
private Collection<GrantedAuthority> authorities;
}
[@Data]
@Data 어노테이션은 @Getter @Setter @ToString @EqualsAndHashCode @RequiredArgsConstructor 역할을 한다. SiteUser에는 final이 붙은 필드가 없기 때문에 다음과 같은 default 생성자만 가지고 있다.
public SiteUser() {}
[@Builder]
이 메서드를 이용하면 다음과 같은 모든 필드를 가진 생성자가 생성되며, 컴파일러는 더 이상 default 생성자를 제공하지 않는다.
public SiteUser(Long id, String email, String password, String username, Collection<GrantedAuthority> authorities) {
this.id = id;
this.email = email;
this.password = password;
this.username = username;
this.authorities = authorities;
}
Mybatis는 결과를 매핑할 때, 파라미터 없는 생성자로부터 객체를 얻고 setter 메서드를 호출하기 때문에 default 생성자가 없는 부분에서 문제가 생긴다.
문제 해결
default 생성자를 만들어 주면 된다. 다음과 같이 @NoArgsConstructor를 추가해준다.
NoArgsConstructor를 추가해주면 Builder에 오류 표시가 뜬다.
Lombok 공식 문서 중(中)
applying @Builder to a class is as if you added @AllArgsConstructor(access = AccessLevel.PACKAGE) to the class and applied the @Builder annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself.
만약에 어떤 형태의 생성자던지 클래스 파일에 존재하면 AllArgsConstructor가 생성되지 않는다. 여기서는 NoArgsConstructor를 통해 default 생성자가 생성이 되었고 따라서 Builder에 필요한 모든 인자를 가진 생성자가 생성되지 않아 에러가 생긴다.
따라서 @AllArgsConstructor도 추가해주어야 한다.
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SiteUser implements UserDetails {
private Long id;
private String email;
private String password;
private String username;
private Collection<GrantedAuthority> authorities;
}
정리
에러의 원인 : Lombok 어노테이션의 미숙한 사용
에러의 해결 : @NoArgsConstructor와 @AllArgsConstructor 추가