ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • DTO(혹은 VO)를 상속 받아서 사용할 경우 주의할 점!
    프로그래밍 언어/자바 & 코틀린 2018. 9. 18. 20:48


    오늘 업무에서 배운 점은 DTO(혹은 VO)를 사용할 때이다.


    * 여기서 DTO는 Data Transfer Object(데이터 전송 객체), VO는 Value Object(값 객체)를 의미하는데, 둘 다 프로세스 간에 데이터를 전달하는 객체로 이해하면 된다. 단, VO는 Read Only라는 차이점이 있다.


    DTO간에 상속을 받아서 부모 DTO의 객체도 함께 쓰려고 할 때 주의할 점을 배웠다. DTO 형태로 파라미터를 던지는데, XML쪽에서 


    에러를 계속해서 뱉었다. 로그에서 parameterType은 DTO형태인데 HashMap이 넘어온다고 말했다.


    우리 본부는 DAO에서 공통된 클래스에서 sqlSession을 맺고 끊으면서 DML(select, update, insert, delete)을 위한 메서드를 사용한다. 


    원인을 못 찾고 여기저기 파라미터 넘어가는 걸 찍어보다가 DTO객체가 DB접근을 위한 공통된 클래스에서 HashMap으로 가공되어


    넘어가고 있었다. 


    왠걸. XML에서 parameterType을 HashMap으로 변경해도 계속해서 NULL값을 받아왔다. 또 열심히 print를 찍어보다가


    set해둔 값들이 안 넘어가는 걸 보았고, 그 객체들은 파라미터인 DTO의 부모 DTO 객체였다.


    정리하자면,


    DTO를 사용할 때, 다른 DTO를 상속받아서 사용하고 싶다면 HashMap에 담으면 안된다! 는 것이었다.


    자식 DTO에서 부모 DTO의 객체를 바로 접근할 수 있지만, 자식 DTO를 HashMap에 담는 순간, 부모 DTO의 객체는 사용하지 못한다.


    코드로 간단히 구현해보았다.


    1. 자식 DTO인 ChildDTO. ParentDTO를 상속받는다.

    public class ChildDTO extends ParentDTO{ // ParentDTO를 부모 클래스로 상속받음 - 자식 DTO

    private String childValue = "";

    public String getChildValue() {
    return childValue;
    }

    public void setChildValue(String childValue) {
    this.childValue = childValue;
    }
    }


    2. 부모 DTO인 ParentDTO


    public class ParentDTO { // 부모 DTO

    private String parentValue = "";

    public String getParentValue() {
    return parentValue;
    }

    public void setParentValue(String parentValue) {
    this.parentValue = parentValue;
    }
    }


    3. Main 메서드


    public class TestMain {

    public static void main(String[] args){
    ChildDTO childDTO = new ChildDTO();

    childDTO.setParentValue("이것은 부모 DTO의 객체");

    System.out.println("자식 DTO에서 부모 DTO로 바로 접근했을 경우 부모 객체의 값: "
    + childDTO.getParentValue());

    /* DTO를 Map 형식으로 바꿔줌 */
    Map<String, Object> param = new HashMap<>();
    try {
    Field[] fields = childDTO.getClass().getDeclaredFields();

    for (int i = 0; i <= fields.length - 1; i++) {
    fields[i].setAccessible(true);
    param.put(fields[i].getName(), fields[i].get(childDTO));
    }
    }catch (IllegalAccessException e){
    e.printStackTrace();
    }

    System.out.println();
    System.out.println("자식 DTO를 HashMap에 담았을 경우, 결과 값: "+param.toString());

    }
    }


    아래의 결과를 보면, 자식 DTO에서 부모 DTO의 객체로 곧바로 접근하면 값을 받아오는 걸 볼 수 있다.


    그리고 다음 줄을 보면, childDTO를 담은 HashMap을 출력했더니, ParentDTO의 객체는 존재하지 않고, childDTO의 객체만 존재한다는 걸 확인할 수 있다.

    (중간에 나오는 코드들은 Object를 Map형식으로 바꿔주는 코드이다.)




    Map형식으로 바꿀 때 childDTO를 읽어서 Map으로 바꿔주니 당연히 childDTO만 객체로 받겠지!라고 생각할 수 있지만, 


    착각할 수 있는 부분인 것 같다. 실제로 레거시 소스가 앞에서 말한 착각할 수 있는 방식대로 개발되어 있었으니까.

    (현재는 사용하지 않는 메서드로 보여서 수정하지 않은 것으로 보인다.)





Designed by Tistory.