mybatis에서 select문을 실행시킬 때 객체에 저장하는 과정에서
아래와 같은 에러가 발생했다.
error:org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: Error instantiating class 클래스명 with invalid types () or values (). Cause: java.lang.NoSuchMethodException: 클래스명<init>() |
select 결과를 저장하는 클래스는 아래와 같은 형식이었다.
public class Test { private int a; private int b; public Test(int a, int b) { this.a = a; this.b = b; } // getter, setter.. } |
파라미터가 있는 생성자가 있으면서
default 생성자가 없는 클래스였던거다.
파라미터 있는 생성자를 만들 때는 default constructor를 만드는 것을 권장한다는 말을 들었는데도
안만들었던 이유는
Test 클래스를 만들 때는 반드시 a, b 파라미터가 생성시부터 항상 존재하게 하려는 의도로 만든 것이었다.
에러가 뜨자마자 default constructor가 없어서 나는 에러임을 감지했지만,
다른 방법이 있지 않을까 해서 mybatis가 select한 후 객체에 저장하는 부분을 찾아봤다.
mybtis가 자바의 reflection을 이용해서, 저장할 인스턴스를 생성시키고, 매핑을 시켜주는데.
그 때 ObjectFactory 라는 클래스를 이용한다.
create 메소드가 두개 있는데 하나는 기본 생성자 처리,
또 하나는 파라미터가 있는 생성자 처리이다.
디폴트 생성자가 없으니 인스턴스를 생성하지 못하고 익셉션을 내뱉는 것이다.
그렇다고 공개적인 디폴트 생성자는 만들고 싶지 않았기 때문에,
디폴트 생성자를 호출할 수 없도록 private으로 만들고
인스턴스를 생성시켜주는 용도의 static 메소드를 하나 만들어서 사용해서 해결했다.
(앞으로 파라미터 있는 생성자를 만들 때는 반드시 디폴트 생성자를 생성할 것)
public class Test { private int a; private int b; private Test() {} // 디폴트 생성자 // 인스턴스 생성 메소드 public static Test createInstance(int a, int b) { Test test = new Test(); test.a = a; test.b = b; return test; } // getter, setter.. } |
그런데 mybatis는 어찌 private으로 되어있는 생성자의 접근이 가능했을까?
마이바티스에서 사용되는 Reflection 클래스에서
타깃 클래스들의 생성자 접근 옵션을 접근 가능으로 바꾸기 때문이다.
constructor.setAccessible(true);
이렇게 세팅을 하기 때문에 어떠한 접근제한자이더라도 mybatis는 접근할 수 있다.
'개발 > Database' 카테고리의 다른 글
timestamp의 가장 큰 값 (0) | 2016.09.12 |
---|---|
(MyBatis) Mysql tinyint(1) boolean이 integer로 바뀌는 현상 (0) | 2015.09.17 |
[iBatis/myBatis] #와 $의 차이점 (6) | 2013.04.11 |
MySql] JOIN 속도를 빠르게! EXPLAIN, STRAIGHT_JOIN (3) | 2012.11.18 |
java + temporary table. 임시테이블 사용하기. MYSQL (0) | 2012.10.26 |