Java&Web

[MyBatis] Enum을 MyBatis 환경에서 사용하기

프로그래민 2021. 1. 12. 01:45
반응형

Java 서버단에서 상수를 처리함에 있어서 여러방법이 있다. 보통 final을 붙여서 상수를 선언하여 처리하는 것이 일반적이지만 성질이 비슷한 상수가 다수가 존재한다면 Enum 클래스를 이용하여 처리할 수 있다. Enum 클래스에 대한 자세한 내용은 다른 포스팅에서 다룰 예정이고, 이번 포스팅에선 이러한 Enum 클래스를 MyBatis 환경에서 적용시키는 실습을 해보았다.

다음과 같은 과정을 거쳐 Springboot에서 Enum 클래스를 MyBatis에 적용시켜 보았다.

 

Enum 클래스 생성

1
2
3
4
5
6
7
8
9
10
11
12
public enum Status {
    UNCHECKED(1),
    APPROVED(2),
    BLOCKED(3);
 
    @Getter
    private final int statusCode;
 
    Status(int statusCode) {
        this.statusCode = statusCode;
    }
}
                                                                                                              

DB상에서는 code인 1, 2, 3으로 관리가 되는 Status Enum 클래스를 생성했다. 1, 2, 3이 각 UNCHECKED, APPROVED, BLOCKED으로 보여질 수 있도록 선언해주고, statusCode라는 변수를 이용해 getter와 생성자를 만들어줌으로써 1, 2, 3을 얻을 수 있도록 해주었다.

 

TypeHandler 클래스 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class StatusTypeHandler<extends Enum<E>> implements TypeHandler<Status> {
    private Class<E> type;
 
    public StatusTypeHandler(Class<E> type) {
        this.type = type;
    }
 
    public void setParameter(PreparedStatement preparedStatement, int i, Status status, JdbcType jdbcType) throws
        SQLException {
        preparedStatement.setInt(i, status.getStatusCode());
    }
 
    @Override
    public Status getResult(ResultSet resultSet, String s) throws SQLException {
        int statusCode = resultSet.getInt(s);
        return getStatus(statusCode);
    }
 
    @Override
    public Status getResult(ResultSet resultSet, int i) throws SQLException {
        int statusCode = resultSet.getInt(i);
        return getStatus(statusCode);
    }
 
    @Override
    public Status getResult(CallableStatement callableStatement, int i) throws SQLException {
        int statusCode = callableStatement.getInt(i);
        return getStatus(statusCode);
    }
 
    private Status getStatus(int statusCode) {
        try {
            Status[] enumConstants = (Status[])type.getEnumConstants();
            for (Status status : enumConstants) {
                if (status.getStatusCode() == statusCode) {
                    return status;
                }
            }
            return null;
        } catch (Exception exception) {
            throw new TypeException("Can't make enum object '" + type + "'", exception);
        }
    }
}
    

Status Enum을 생성 후 MyBatis 환경에서 mapping을 위해 사용되는 StatusTypeHandler를 구현해주었다. TypeHandler는 MyBatis가 SELECT시에 PreparedStatement에 파라미터를 설정하고 ResultSet에서 값을 가져올때마다 적절한 Java 타입의 값을 가져오도록 해주고, INSERT시에 PreparedStatement에 적절한 Java 타입의 값을 지정 해준다.

즉, 위의 Status와 StatusTypeHandler를 본다면, DB상의 status code 값인 1, 2, 3에 대해서 mapper를 통한 조회를 한다면 Java 상에서 Status Enum을 통해 각 UNCHECKED, APPROVED, PROHIBITED의 값으로 매핑 해주는 역할을 StatusTypeHandler가 해주는 것이다.

 

Enum에 TypeHandler 클래스 생성 및 TypeHandler를 Config에 등록

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public enum Status {
    ALL(0),
    UNCHECKED(1),
    APPROVED(2),
    BLOCKED(3);
 
    @Getter
    private final int statusCode;
 
    Status(int statusCode) {
        this.statusCode = statusCode;
    }
 
    @MappedTypes(Status.class)
    public static class TypeHandler extends StatusTypeHandler<Status> {
        public TypeHandler() {
            super(Status.class);
        }
    }
}
                                                           

앞서 정의한 Status 클래스에 StatusTypeHandler를 상속받는 TypeHandler를 작성해준다.

1
2
3
4
5
6
7
8
9
10
11
12
public class DatabaseConfig {
    private final ApplicationContext applicationContext;
 
    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        sqlSessionFactoryBean.setMapperLocations(applicationContext.getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setTypeHandlers(new TypeHandler[] {
            new Status.TypeHandler()
        });
}
     

그 후 DB Config 클래스에 Status의 TypeHandler를 등록해준다.

 

결과확인

Status Enum 형으로 선언된 DTO의 변수

DTO에 가지는 변수를 Status Enum 형으로 선언해주었다.

mapper에 선언된 select문 일부

그 후 위와 같은 조회문을 mapper에 선언해주었다.

 

DB에 저장된 내용
DB 조회 후 Springboot의 콘솔창

그 결과 DB에 저장된 1, 2가 Springboot에선 각 각 APPROVED, UNCHECKED로 나오는 것을 확인 할 수 있었다.

 

 

출처
goodgid.github.io/MyBatis-Handling-TypeHandler-Enum/
www.holaxprogramming.com/2015/11/12/spring-boot-mybatis-typehandler/
sejoung.github.io/2019/10/2019-10-07-mybatis_enum/#Mybatis-ENUM-%EC%82%AC%EC%9A%A9%EB%B2%95
egloos.zum.com/springmvc/v/440928

 

반응형