使用数据库中的值填充枚举

Jac*_*ine 24 java enumeration hashmap

我有一个映射String-> Integer的表.

我不是静态地创建枚举,而是想用数据库中的值填充枚举.这可能吗 ?

所以,而不是静态地删除:

public enum Size { SMALL(0), MEDIUM(1), LARGE(2), SUPERSIZE(3) };
Run Code Online (Sandbox Code Playgroud)

我想动态创建这个枚举,因为数字{0,1,2,3}基本上是随机的(因为它们是由数据库的AUTOINCREMENT列自动生成的).

Jon*_*eet 31

编号时,枚举始终是固定的.你能做到这一点的唯一方法是动态生成相关的字节码.

话虽如此,你应该弄清楚你真正感兴趣的枚举的哪些方面.大概你不想switch在它们上面使用语句,因为这意味着静态代码并且你不会静态地知道这些值. ..同样代码中的任何其他引用.

如果你真的只是想从地图StringInteger,你可以使用Map<String, Integer>你填写在执行时,就大功告成了.如果你想要这些EnumSet功能,那么以相同的效率再现它们会有些棘手,但是通过一些努力可能是可行的.

因此,在考虑实施之前,我建议您先了解一下您的实际需求.

(编辑:我一直在假设这个枚举是完全动态的,即你不知道名字甚至知道有多少个值.如果名称集是固定的,你只需要从数据库中获取ID ,这是一个非常不同的问题 - 请参阅Andreas的回答.)


And*_*son 26

这有点棘手,因为这些值的数量发生在类加载时.因此,您需要静态访问数据库连接.

尽管我重视他的答案,但我认为Jon Skeet这次可能是错的.

看看这个:

public enum DbEnum {
    FIRST(getFromDb("FIRST")), SECOND(getFromDb("second"));

    private static int getFromDb(String s) {
        PreparedStatement statement = null;
        ResultSet rs = null;
        try {
            Connection c = ConnectionFactory.getInstance().getConnection();
            statement = c.prepareStatement("select id from Test where name=?");
            statement.setString(1, s);
            rs = statement.executeQuery();
            return rs.getInt(1);

        }
        catch (SQLException e) {
           throw new RuntimeException("error loading enum value for "+s,e);
        }
        finally {
            try {
                rs.close();
                statement.close();
            } catch (SQLException e) {
                //ignore
            }
        }
        throw new IllegalStateException("have no database");
    }

    final int value;

    DbEnum(int value) {
        this.value = value;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你假设你在*编译时知道*将会有多少值,以及它们应该被调用的内容.如果是这样,那就没关系了 - 但我没有在问题中看到任何暗示这一点的东西.(我认为您的查询也应该选择ID,而不仅仅是1 :) (5认同)
  • 一个信息性的回应,提醒我们关于枚举的面向对象方面 - 谢谢,安德烈亚斯. (2认同)

小智 6

改进Andreas的功能,您可以将数据库的内容加载到映射中,以减少所需的数据库连接数.

public enum DbEnum {
    FIRST(getFromDb("FIRST")),
    SECOND(getFromDb("second"));

    private Map<String,Integer> map;
    private static int getFromDB(String s)
    {
        if (map == null)
        {
           map = new HashMap<String,Integer>();
           // Continue with database code but get everything and
           // then populate the map with key-value pairs.
           return map.get(s);
        }
        else {
            return map.get(s); }
    }
}
Run Code Online (Sandbox Code Playgroud)