0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Java】DBの定義を反映したenumで、DBに保存する内容とenumのnameが食い違った場合への対処

Posted at

問題の内容

DBのテーブル定義をそのまま写したenumで、予約語と定義が被ったため、_を付けて定義しました。

問題の発生したenum
public enum Moge {
    hoge("hoge"), fuga("fuga"), _native("native"); //nativeは予約語

/* 省略 */

ここで、Jdbcへのクエリ結果をEnum.valueOfを用いてマッピングしていましたが、DBから取れる値はnativeであり、_nativeと異なるため、マッピングできませんでした。

対処

DBから取れる値に対応するフィールドを伝えるアノテーションを作り、リフレクションでアノテーションを処理することでマッピングできるようにしました。

MapByValue
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MapByValue {
    String value();
}
アノテーションを付与した様子
public enum Moge {
    hoge("hoge"), fuga("fuga"),
    @MapByValue(value = "native") _native("native"); //nativeは予約語

/* 以下省略 */
アノテーションを処理する様子
@SuppressWarnings("unchecked")
private Object mapEnum(Class<?> clz, String columnValue) {
    /* 省略 */

    String finalColumnValue = columnValue;
    columnValue = Arrays.stream(clz.getFields()) //フィールドを全部取得
            .filter(it -> {
                //MapByValueアノテーションが付与され、かつその値とcolmunValueが等しい場合
                MapByValue mapByValue = it.getAnnotation(MapByValue.class);
                return mapByValue != null && mapByValue.value().equals(finalColumnValue);
            })
            .findFirst()
            .map(Field::getName) //付与されたフィールドの名前を使う
            .orElse(finalColumnValue);

    return clz.cast(Enum.valueOf((Class<Enum>) clz, columnValue));
}

@SuppressWarnings("rawtypes")
@Override
protected Object getColumnValue(ResultSet rs, int index, PropertyDescriptor pd) throws SQLException {
    Class<?> clz = pd.getPropertyType(); //型情報の取得

    /* 省略 */

    if (clz.isEnum()) { //enumの場合
        byte[] bytes = rs.getBytes(index);
        if (isEmpty(bytes)) {
            return null;
        }

        return mapEnum(clz, new String(bytes, Charset.forName("UTF-8")));
    }

    /* 省略 */

別の案

Jsonから変換する都合で値からenumへ変換する関数を全てのenumが持っていたため、リフレクションからこれを利用することも考えましたが、アノテーション振って処理した方が汎用性が高いと判断しました。
valueOfOverrideできれば一番よかったんですが……。

参考にさせていただいた記事

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?