作成日: 2014/01/04

メモ: java でコードとコード値を分離するサンプル

概要

java で列挙を使ったコードと、コード値を分離するサンプルを作ってみました。 環境は JDK 1.7、PostgreSQL 9.2 です。 作成には Eclipse 3.7 Indigo Pleiades All in One (MergeDoc Project で公開されています) を利用させていただきました。ありがたく深謝いたします。

※なお、コード値の保持には OTLT (One True Lookup Table: 単一参照テーブル) を使っています。 OTLT には賛否両論ありますので、OTLT にしない場合は、テーブルからのコード値のロード部分を適宜変更してくださいませ m(_*_)m

サンプルソース
package sample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;


public class Main {

    /**
     * コード値の動的ロードのサンプル
     */
    public static void main(String[] args) {

        try {

            //
            // コード値をロードする
            //
            DynCodeImpl.loadValues();

            //
            // ロードしたコード値を表示してみる
            //

            // 果物
            System.out.format("%s: [%s]\n", Fruit.ORANGE.name(), Fruit.ORANGE.getValue());
            System.out.format("%s: [%s]\n", Fruit.APPLE.name(), Fruit.APPLE.getValue());
            // 動物
            System.out.format("%s: [%s]\n", Animal.DOG.name(), Animal.DOG.getValue());
            System.out.format("%s: [%s]\n", Animal.CAT.name(), Animal.CAT.getValue());

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * コード値を取得するためのインタフェース
     */
    interface DynCode {
        String getValue();
    }

    /**
     * コード値を動的にロード・取得するための実装
     */
    public static class DynCodeImpl implements DynCode {

        private String type;
        private String name;
        private String value = null;

        public DynCodeImpl(String type, String name) {
            this.type = type;
            this.name = name;
        }

        @Override
        public String getValue() {

            if (this.value == null) {

                String result = "";

                Map<String, String> nameToValueMap = dyncodeMap.get(this.type);
                if (nameToValueMap != null) {
                    String val = nameToValueMap.get(this.name);
                    if (val != null) {
                        result = val;
                    }
                }

                this.value = result;
            }

            return this.value;
        }

        /**
         * コード値を保持するマップ
         */
        private static Map<String, Map<String, String>> dyncodeMap = new HashMap<String, Map<String, String>>();

        /**
         * コード値をロードする
         */
        public static void loadValues() {

            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;

            try {

                Class.forName("org.postgresql.Driver");

                conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/sample", "sample", "sample");

                StringBuilder sql = new StringBuilder();
                sql.append("SELECT * FROM DYNCODE");
                sql.append(" ORDER BY TYPE, NAME");

                ps = conn.prepareStatement(sql.toString());

                rs = ps.executeQuery();

                while (rs.next()) {

                    String type = rs.getString("TYPE");
                    String name = rs.getString("NAME");
                    String value = rs.getString("VALUE");

                    Map<String, String> nameToValueMap = dyncodeMap.get(type);
                    if (nameToValueMap == null) {
                        nameToValueMap = new HashMap<String, String>();
                    }
                    nameToValueMap.put(name, value);
                    dyncodeMap.put(type, nameToValueMap);
                }

            } catch (Exception ex) {

                ex.printStackTrace();

            } finally {

                if (rs != null) {
                    try {
                        rs.close();
                    } catch (SQLException ex) {
                        ex.printStackTrace();
                    }
                }

                if (ps != null) {
                    try {
                        ps.close();
                    } catch (SQLException ex) {
                        ex.printStackTrace();
                    }
                }

                if (conn != null) {
                    try {
                        conn.close();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 果物
     */
    private enum Fruit implements DynCode {

        ORANGE,
        APPLE,
        ;

        private DynCode dynCode;

        private Fruit() {
            this.dynCode = new DynCodeImpl(this.getDeclaringClass().getSimpleName(), this.name());
        }


        @Override
        public String getValue() {
            return dynCode.getValue();
        }
    }

    /**
     * 動物
     */
    private enum Animal implements DynCode {

        DOG,
        CAT,
        ;

        private DynCode dynCode;

        private Animal() {
            this.dynCode = new DynCodeImpl(this.getDeclaringClass().getSimpleName(), this.name());
        }


        @Override
        public String getValue() {
            return dynCode.getValue();
        }
    }
}
テーブル定義とか
DROP TABLE DYNCODE;
CREATE TABLE DYNCODE (
    TYPE VARCHAR(20) NOT NULL,
    NAME VARCHAR(20) NOT NULL,
    VALUE VARCHAR(20) NOT NULL,
    PRIMARY KEY (TYPE, NAME)
);

INSERT INTO DYNCODE VALUES ('Fruit', 'ORANGE', '00001');
INSERT INTO DYNCODE VALUES ('Fruit', 'APPLE', '00002');
INSERT INTO DYNCODE VALUES ('Animal', 'DOG', 'ABC010');
INSERT INTO DYNCODE VALUES ('Animal', 'CAT', 'ABC020');