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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/851466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:10:34  来源:igfitidea点击:

Populate an enum with values from database

hashmapenumerationjava

提问by Jacques René Mesrine

I have a table which maps String->Integer.

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

Rather than create an enum statically, I want to populate the enum with values from a database. Is this possible ?

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

So, rather than delcaring this statically:

所以,而不是静态地声明它:

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

I want to create this enum dynamically since the numbers {0,1,2,3} are basically random (because they are autogenerated by the database's AUTOINCREMENT column).

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

采纳答案by Jon Skeet

No. Enums are always fixed at compile-time. The only way you could do this would be to dyamically generate the relevant bytecode.

不。枚举总是在编译时固定的。您可以执行此操作的唯一方法是动态生成相关字节码。

Having said that, you should probably work out which aspects of an enum you're actually interested in. Presumably you weren't wanting to use a switchstatement over them, as that would mean static code and you don't know the values statically... likewise any other references in the code.

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

If you really just want a map from Stringto Integer, you can just use a Map<String, Integer>which you populate at execution time, and you're done. If you want the EnumSetfeatures, they would be somewhat trickier to reproduce with the same efficiency, but it may be feasible with some effort.

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

So, before going any further in terms of thinking about implementation, I suggest you work out what your real requirements are.

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

(EDIT: I've been assuming that this enum is fully dynamic, i.e. that you don't know the names or even how many values there are. If the set of names is fixed and you onlyneed to fetch the ID from the database, that's a very different matter - see Andreas' answer.)

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

回答by aleemb

Enums are not dynamic, so the short answer is that you can't do it.

枚举不是动态的,所以简短的回答是你不能这样做。

Also have a look at Stack Overflow question Dynamic enum in C#.

另请查看 Stack Overflow 问题Dynamic enum in C#

回答by Luixv

In all the languages I know enums are static. The compiler can make some optimizations on them. Therefore the short answer is no, you can't.

在我知道的所有语言中,枚举都是静态的。编译器可以对它们进行一些优化。因此,简短的回答是否定的,你不能。

The question is why you want to use an enum in this way. What do you expect? Or in other words why not use a collection instead?

问题是为什么要以这种方式使用枚举。你能指望什么?或者换句话说,为什么不使用集合呢?

回答by Andreas Petersson

This is a bit tricky, since the population of those values happens at class-load time. So you will need a static access to a database connection.

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

As much as I value his answers, I think Jon Skeet may be wrong this time.

尽管我很看重他的回答,但我认为 Jon Skeet 这次可能是错的。

Take a look at this:

看看这个:

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

回答by kgiannakakis

You need to replicate in code what is in the database (or vice-versa). See this questionfor some good advices.

您需要在代码中复制数据库中的内容(反之亦然)。请参阅此问题以获取一些好的建议。

回答by Tigertron

Improving on what Andreas did, you can load the contents of the database into a map to reduce the number of database connections needed.

改进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); }
    }
}