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

2022-09-01 13:46:49

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

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

所以,而不是静态地去关心这一点:

public enum Size { SMALL(0), MEDIUM(1), LARGE(2), SUPERSIZE(3) };

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


答案 1

不。枚举始终在编译时是固定的。执行此操作的唯一方法是按顺序生成相关的字节码。

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

如果你真的只是想要一个从 到 的映射,你可以使用一个在执行时填充的映射,你就完成了。如果您想要这些功能,以相同的效率复制它们会有些棘手,但是通过一些努力可能是可行的。StringIntegerMap<String, Integer>EnumSet

因此,在进一步考虑实现之前,我建议您弄清楚您的真正需求是什么。

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


答案 2

这有点棘手,因为这些值的填充发生在类加载时间。因此,您将需要对数据库连接进行静态访问。

尽管我很看重他的答案,但我认为乔恩·斯基特这次可能是错的。

看看这个:

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;
    }
}