본문 바로가기

Programming!

JPA - 필드에 Trim 적용하기

두가지의 방법이 있다. 첫번째는 JBoss-Hibernate에서 제공되는 @ColumnTransformer를 사용하는 방법과 Listener를 적용하는 방법.


DB에 종속적인 모델이지만, 개인적으로는 첫번째 방법인 ColumnTransformer를 추천한다.


ColumnTransformer를 적용하는 방법.

..
    @ColumnTransformer(write="trim(?)")
    @Column(name = "title", nullable = false)
    private String title;

..



TrimListener를 만들어 적용하는 방법

@Trim Annotaion을 지정한다고 보면, Annotaion의 적용 대상은 method나 field일 것이다. 그러니 @interface의 적용 대상을 field, method로 지정한다.


import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
public @interface Trim {
}



적용 대상이 EntityListeners이므로 이름을 TrimListener로 지정하고 작성해 보자.

1. @Trim Annotaion이 있는 필드를 찾아서 반환하는 메스드를 먼저 만들어 둔다.

public class TrimListener {

    private final Map<Class<?>, Set<Field>> trimFieldMap = new HashMap<Class<?>, Set<Field>>();


    private Set<Field> getTrimAnnotationFields(Class<?> entity) throws Exception {
        Set<Field> trimFields = trimFieldMap.get(entity);
        if (trimFields == null) {
            trimFields = new HashSet<Field>();
            Field[] fields = entity.getDeclaredFields();
            for (Field field : fields) {
                if (field.getType().equals(String.class) && field.getAnnotation(Trim.class) != null) {
                    field.setAccessible(true);
                    trimFields.add(field);
                }
            }
            trimFieldMap.put(entity, trimFields);
        }
        return trimFields;
    }



2. 1에서 반환한 Trim Annotaion의 목록 field를 실제 trim처리하는 메소드를 만든다. Listener이므로 @PostLoad에서 처리하도록 한다.

    @PostLoad
    public void replacePostLoad(final Object entity) throws Exception {
        Set<Field> trimFields = getTrimAnnotationFields(entity.getClass());
        for (Field trimField : trimFields) {
            String trimFieldValue = (String) trimField.get(entity);
            if (!StringUtils.isEmpty(trimFieldValue)) {
                trimField.set(entity, trimFieldValue.trim());
            }
        }
    }



3. 적용할 클래스 field에 @Trim을 적용을 하고, EntityListener에 등록하자.

@Data
@NoArgsConstructor
@EntityListeners(value = { AuditingEntityListener.class, TrimListener.class })
@Entity(name = "Faq")
@Table(name = "faq")
public class Faq implements Autocompletable<Faq> {
...

    @Trim
    @Column(name = "title", nullable = false)
    private String title;

...





그냥 TRIM 함수 사용하기

@Modifying

@Query("update XxxEntity o set o.name = TRIM(:name) where o.id = :id")

void updateOptGoodsCd(@Param("id") Long id, @Param("name") String name);


실제 테스트를 돌려보면 find/save시에 trim이 적용된 것을 볼 수 있다.