본문 바로가기

Spring Framework

자바 Reflection 의 활용, EntityUtil 클래스 만들어 보기

반응형

엔티티 멤버변수에 내가 원하는 멤버변수를 제외하고 나머지를 모두 null 처리 하려면? 

서로 다른 클래스의 오브젝트지만 데이터타입과 변수명이 동일한 멤버변수의 값을 체크해서 복사시키려면?

위와 같은 문제를 실제로 해결하고자 직접 Reflection 과 제너릭을 이용하여 일반화해서 사용할 수 있는 클래스를 직접 만들어봤다. 

Entity Object 에서 필요한 기능들을 Reflection 으로 구현

  • Entity 객체에서 특정 멤버변수만 빼고 모두 null 로 값을 바꾸려면? (가령 user 를 탈퇴시킬 때, user entity의 정보를 날리기 위해 해당 엔티티 오브젝트의 멤버변수를 null 처리, 그리고 특정 필드는 그대로 두도록 하려면?)
    • → setAllNullExceptSpecificFields 메서드
  • 서로 다른 class 로부터 만들어진 Entity 간 서로 겹치는 멤버변수들을 모두 복사하려면? (user → usertemp로 이동할 때)
    • → copyFieldValuesToNewObj 메서드
```java
import com.google.common.base.Defaults;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.springframework.util.ReflectionUtils;

public class EntityUtil {

  private static List<Class<?>> PRIMITIVE_TYPES =
      Arrays.asList(
          boolean.class,
          byte.class,
          short.class,
          int.class,
          long.class,
          float.class,
          double.class,
          char.class);

  public static <T> void setAllNullExceptSpecificFields(T targetObj, String... exceptFields) {

    ReflectionUtils.doWithFields(
        targetObj.getClass(),
        field -> {
          field.setAccessible(true);
          Class<?> type = field.getType();

          if (exceptFields.length > 0
              && stringContainsItemFromList(field.getName(), exceptFields)) {

          } else if (PRIMITIVE_TYPES.contains(type)) {
            field.set(targetObj, Defaults.defaultValue(type));
          } else {
            field.set(targetObj, null);
          }
        });
  }

  public static <T> void copyFieldValuesToNewObj(T inputObj, T targetObj) {

    HashMap<String, Object> typeFieldMap = new HashMap<>();

    ReflectionUtils.doWithFields(
        inputObj.getClass(),
        field -> {
          field.setAccessible(true);
          String fieldNameKey = field.getType().toString().concat(field.getName());
          typeFieldMap.put(fieldNameKey, field.get(inputObj));
        });

    ReflectionUtils.doWithFields(
        targetObj.getClass(),
        field -> {
          field.setAccessible(true);
          String targetFieldName = field.getType().toString().concat(field.getName());
          if (typeFieldMap.containsKey(targetFieldName)) {
            field.set(targetObj, typeFieldMap.get(targetFieldName));
          }
        });
  }

  public static boolean stringContainsItemFromList(String inputStr, String[] items) {
    return Arrays.stream(items).filter(inputStr::contains).findAny().isPresent();
  }
}
```
반응형