반응형
1. 에러 발생 상황
- MyBatis(마이바티스) 를 통해서 DB 에서 데이터를 조회하려는 도중 아래와 같은 에러가 발생.
### Cause: java.lang.IndexOutOfBoundsException: Index 4 out of bounds for length 4] with root cause java.lang.IndexOutOfBoundsException: Index 4 out of bounds for length 4 at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64) ~[na:na] at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70) ~[na:na] at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248) ~[na:na] at java.base/java.util.Objects.checkIndex(Objects.java:372) ~[na:na] at java.base/java.util.ArrayList.get(ArrayList.java:459) ~[na:na] at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createUsingConstructor(DefaultResultSetHandler.java:709) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createByConstructorSignature(DefaultResultSetHandler.java:694) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:658) ~[mybatis-3.5.7.jar:3.5.7] at org.apache.ibatis.executor.resultset.DefaultResultSetHandler.createResultObject(DefaultResultSetHandler.java:631) ~[mybatis-3.5.7.jar:3.5.7]
- 에러메시지를 보았을 때에는 무언가 배열과 관련 있는 것처럼 보였지만, 검색을 통해 확인해보았을 때는 Lombok 을 사용하면서 발생한 것이다.
2. 원인
- 간단한 예제로 Lombok 을 사용한 Entity 는 아래와 같다.
@Entity
@Getter
@Setter
@Builder
@AllArgsConstructor
@ToString
@DynamicInsert
public class Todo {
@Id
@GeneratedValue
@Column(name = "todo_id")
private Long id;
private String item;
private String date;
private boolean completed;
private String time;
private LocalDateTime writeDate;
private LocalDateTime updateDate;
@Column(columnDefinition = "varchar(1) default 'Y'")
private String useYn;
}
- MyBatis 를 통해서 조회하고자 하는 쿼리는 다음과 같다.
@Mapper
@Repository
public interface MybatisTestMapper {
@Results({
@Result(property = "completed", column = "COMPLETED"),
@Result(property = "date", column = "DATE"),
@Result(property = "time", column = "TIME")
})
@Select(
"SELECT COMPLETED, DATE, TIME, USE_YN FROM TODO"
)
List<Todo> testSelect();
}
- 해당 메소드를 호출하게 되면 위와 같은 에러가 발생한다.
- 원인은 @Results 의 ResultMap 의 특성 때문으로, 해당 기능을 사용할 경우 MyBatis 가 미리 해당 인스턴스를 생성한다.
- MyBatis 는 데이터를 아래와 같은 순서로 전달한다.
- 기본 생성자를 통해 객체를 생성
- 생성된 객체에 Setter 연산자를 사용해 데이터를 변경
- 하지만 위 Entity 에서는 모든 파라미터가 포함된 생성자(@AllArgsConstructor)만 존재만 하고, 기본 생성자를 생성하지 않아 발생한 문제이다.
3. 해결 방법
- 해결방법은 간단하게 기본 생성자를 추가하면 된다.
- Lombok 어노테이션인 @NoArgsConstructor 를 사용하여 추가
- 직접 기본 생성자를 추가
@Entity
@Getter
@Setter
@Builder
@NoArgsConstructor // <- 1. 해당 어노테이션을 추가
@AllArgsConstructor
@ToString
@DynamicInsert
public class Todo {
@Id
@GeneratedValue
@Column(name = "todo_id")
private Long id;
private String item;
private String date;
private boolean completed;
private String time;
private LocalDateTime writeDate;
private LocalDateTime updateDate;
@Column(columnDefinition = "varchar(1) default 'Y'")
private String useYn;
public Todo() {} // <- 2. 직접 기본 생성자를 작성
}
참고
반응형