MyBatis, 공통코드 - ENUM 매핑
가상화폐가격알리미 개발과정에서 공통코드를 사용하기로 했습니다.
<img alt="pasteImage.png" pathname="LHBDAF190204141631.PNG" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/LHBDAF190204141631.PNG" style="border-style:solid; border-width:1px; width:338px" title="pasteImage.png"/>
<br/>
그리고 공통코드는 사용자 정보의 거래소값등에 사용됩니다.
<img alt="pasteImage.png" pathname="2B54S1190204141734.PNG" src="https://static.podo-dev.com/blogs/images/2019/07/10/origin/2B54S1190204141734.PNG" style="border-style:solid; border-width:1px; width:506px" title="pasteImage.png"/>
<br/>
다만 사용자 정보 데이터를 가져와 ClientVo에 매핑되는데, 거래소 공통코드값을 Market Enum값으로 매핑되면 좋을 것 같습니다.
public class ClientVo {
//
private Market marketId;
//
}
<br/>
Market Enum은 다음과 같습니다.
public enum Market{
COINONE,
BITHUMB,
UPBIT,
COINNEST,
KORBIT,
GOPAX,
CASHIEREST,
BITFINEX,
BITTREX,
POLONIEX,
BINANCE,
HUOBI,
HADAX,
OKEX;
}
<br/>
<br/>
<span style="color:#990000">문제는 이렇습니다.
<span style="color:#990000">데이터베이스의 저장된 사용자 정보의 거래소정보가 공통코드 값으로 되어습니다.
<span style="color:#990000">MyBatis가 사용자정보 데이터를 ClientVo 매핑 시킬때, 공통코드 값을 이용해 자동으로 ENUM 값을 주입하였으면 좋겠습니다.
<span style="color:#990000">그리고 또한 사용자 정보를 삽입할 때, ENUM 값을 자동으로 공통코드값으로 데이터가 INSERT 되었으면 좋겠습니다. 오호
<span style="color:#990000">더욱더 좋은것은 이것이 일반화되어 모든 공통코드 값에 적용되는 것입니다.
<br/>
<span style="color:#0000cc">웹검색을 통해서 좋은 소스를 참고하였습니다. 출처는 하단에 기입하였습니다.
<span style="color:#0000cc">해결책은 다음과 같습니다.
<br/>
인터페이스 CodeEnum을 정의합니다.
public interface CodeEnum {
public String getCode();
public static <E extends Enum<E> & CodeEnum> E from(E[] es, String str) {
E rs = null;
for (E b : es) {
if (b.getCode().equalsIgnoreCase(str)) {
return b;
}
}
return rs;
}
}
<br/>
공통코드를 가지고 있는 ENUM은, CodeEnum을 구현하여 정의합니다.
@AllArgsConstructor
public enum Market implements CodeEnum{
COINONE("101"),
BITHUMB("102"),
UPBIT("103"),
COINNEST("104"),
KORBIT("105"),
GOPAX("106"),
CASHIEREST("107"),
BITFINEX("201"),
BITTREX("202"),
POLONIEX("203"),
BINANCE("204"),
HUOBI("205"),
HADAX("206"),
OKEX("207");
@Getter
private final String code;
}
<br/>
<br/>
그리고 MyBatis의 설정파일에 다음과 같이 설정하였습니다.
mybatis-config.xml 입니다. CodeEnum 타입에 대해서는, CodeEnumTypeHandler를 이용하여 매핑하도록 설정하였습니다.
<configuration>
<typeHandlers>
<typeHandler javaType="com.cglee079.coinchatbot.config.id.CodeEnum"
handler="com.cglee079.coinchatbot.config.mybatis.CodeEnumTypeHandler" />
</typeHandlers>
</configuration>
-
3 : CodeEnum 타입에 대해서는
-
4 : CodeEnumTypeHandler를 사용하여 매핑
<br/>
<br/>
<br/>
핸들러는 다음과 같습니다.
public class CodeEnumTypeHandler<E extends Enum<E> & CodeEnum> extends BaseTypeHandler<E> {
private Class<E> type;
public CodeEnumTypeHandler(Class<E> type) {
if (type == null)
throw new IllegalArgumentException("Type argument cannot be null");
this.type = type;
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter, JdbcType jdbcType) throws SQLException {
if (jdbcType == null) {
ps.setString(i, parameter.getCode());
} else {
ps.setObject(i, parameter.getCode(), jdbcType.TYPE_CODE);
}
}
@Override
public E getNullableResult(ResultSet rs, String columnName) throws SQLException {
String s = rs.getString(columnName);
return getCodeEnum(type, s);
}
@Override
public E getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
String s = rs.getString(columnIndex);
return getCodeEnum(type, s);
}
@Override
public E getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
String s = cs.getString(columnIndex);
return getCodeEnum(type, s);
}
public static <T extends Enum<T> & CodeEnum> T getCodeEnum(Class<T> enumClass, String code) {
return EnumSet.allOf(enumClass).stream().filter(type -> type.getCode().equals(code)).findFirst()
.orElseGet(null);
}
}
-
12 : INSERT 또는 UPDATE시 ENUM 값에서 공통코드값을 가져와 삽입/수정 합니다.
-
21, 27, 33 : SELECT시 공통코드값을 이용해 ENUM 타입을 주입합니다.
<br/>
<br/>
이렇게 설정하면 CodeEnum을 구현한 ENUM타입에대해서는 CodeEnumHandler가 적용되어 매핑됩니다.
INSERT 시에는 code 값이, SELECT 시에는 ENUM타입으로 매핑됩니다. 오호
<br/>
<br/>
출처
<a href="https://androphil.tistory.com/707">https://androphil.tistory.com/707</a>
<br/>
<br/>