MDL을 구문을 실행하는 execUpdate와 Select를 실행하는 execQuery에 추가로 Select지만 Java의 일반 객체로 바꿔주는 execHandlerQuery가 있다.
앞서 서비스와 서비스의 교환은 중립적인 메시지 교환이라고 했는데 Rows 객체는 실질적으로 중립적인 객체라고 하기 어렵다. JIT 연결과 SQL Exception을 없에는 등 몇가지 점을 수정하긴 했지만 기본적으로 java.sql.ResultSet을 상속받았기 때문이다.
그래서 잠시 딴 생각을 해보자. ResultSet이 왜 필요한가? 클라이언트 서비스에서 DB서비스에 접근할때 response 될때 정말 필요한것은 Value 그 자체이지 특별히 ResultSet 이라는 인터페이스가 필요하지는 않다. 그리고 이러한 중립적인 Value 객체는 java.util에 많이 있다. 또는 EJB 처럼 POJO를 사용할 수도 있다.
그렇다고
bean.setName(rows.getString("name") ;
bean.setEmpNo(rows.getString("empNo") ;
bean.setSal(rows.getString("sal") ;
와 같이 반복적으로 직접 값을 셋팅하는 것은 불편하다.
개인적으로 어려운 걸 쉽게 만들기는 어렵다고 생각한다. 효율적인 SQL을 만드는 것은 어렵다. 이를 단순히 하이버네트식의 객체 인터페이스로 바꾼다고 해서 어려운 SQL을 쉽게 만들기는 아주아주 어렵다고 생각한다. 다만 복잡한걸 간결하게 만들기는 그렇게까지 어렵지 않다. 복잡하다는 것은 과정이 길다는 것을 말하고 이전의 여러 단계로 거쳐야 하는 과정을 몇단계를 줄여줄 수만 있으면 된다. 아직 이에 대한 연구가 행해진 걸 본적은 없지만 대부분의 버그는 어려운 로직보다는 반복적인 로직에서 좀더 많은 버그가 발생하지 않을까 생각한다. 인간은 기본적으로 반복적인 작업에 최적화 되어 있지 못하다. 그런 것은 컴퓨터에 맡기는 게 좀더 좋다.
ResultSet을 특정 Bean의 List로 바꾸는 것은 리플렉션을 이용하면 간단하다. 그리고 운이 좋게도 Apache Open source인 dbutils에 이미 대부분 구현되어 있어서 베껴왔다. 어느 것이나 마찬가지라고 생각하지만 기존의 사례를 살펴보는 것은 항상 도움되는 일이다.
예컨대 이런식으로 사용한다.
public void testHandler(){
IQueryable query = dc.createUserProcedure("employee@listBy(?)").addParam(10);
ObjectWrapper wrapper = dc.getObjectWrapper(query, new BeanListHandler(Employee.class));
List<Employee> list = (List<Employee>)wrapper.getObject() ;
for(Employee e : list){
System.out.println(e);
}
}
ResultSetHandle 인터페이스의 handle(ResultSet rs) 메소드 하나만 구현하면 되기 때문에 구조는 매우 간단하다. 앞에서 구조적 중복을 없에주는게 프레임워크라고했는데 여기서의 중복은 소스 증복에 가깝기 때문에 알아채는 것은 쉬운일이다.
ArrayHandler :
ResultSet의 첫번째 Row를 Object[]로 바꿔준다.
ArrayListHandler :
ResultSet의 모든 Row를 Object[]의 List로 바꿔준다.
BeanHandler :
첫번째 Row를 POJO Bean으로 바꿔준다.
BeanListHandler :
모든 Row를 POJO Bean의 List로 바꿔준다.
MapHandler :
첫번째 Row를 key(columnName), value의 Map으로 바꿔준다.
MapListHandler :
모든 Row를 Map의 List로 바꿔준다.
LimitMapListHandler :
일부 범위의 Row만 Map의 List로 바꿔준다.
ScalarHandler :
첫번째 Row의 특정 column을 값으로 바꿔준다.
SimpleXMLStringBufferHandler :
모든 Row를 XML 형태의 StringBuffer로 바꿔준다.
CSVStoreHandler :
모든 Row를 CSV 파일 형태로 저장한다.
다시 말하자면 프레임워크는 어렵운걸 쉽게 만들어 주기 보단 복잡한걸 간결하게 만들어주는게 우선이다. 어려운걸 쉽게 만들기가 이론적으로 불가능은 아니지만 무척 어렵기 때문에 - 아이러니 하지만 쉽게 만들 수 있다는건 어려운게 아니다. 물론 혁신의 가능성을 부정하는 것은 아니지만.. - 그런것은 쉽게 도전할 성질의 것이 아니다. 복잡한걸 간결하기 만들기 위해서는 단계를 줄이고 순서를 없애야 한다.
'Framework > Database' 카테고리의 다른 글
Framework (DBController) (0) | 2009.03.12 |
---|---|
Framework -커서(ForwardOnly, Sensitive(=Static)) (0) | 2009.03.12 |
Framework (Rows) (0) | 2009.03.07 |
Framework (IQueryable) (0) | 2009.03.06 |
Framework (DBManager) (0) | 2009.03.04 |