枚举代​​表数据库表

时间:2018-12-05 09:03:32

标签: java enums

我目前处于一种状态,其中XmlConfigurator.Configure(new FileInfo("log4net.config")) MyType表示类型表,其列为:

enum

它用于通过ID Name 方法使用ID参数来标识类型:

byId

我的新要求是还支持Type表中存在的值,我发现answers用于动态枚举,但是接受答案不是这样做

  

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

对于也查找数据库中的值(主要是ID)(例如ID 30),有什么更好的解决方案

public enum MyType {

FIRST_TYPE("First Type", 10),
SECOND_TYPE("Second Type", 20);
public static class Holder {
    static Map<Integer, MyType > idMap = new HashMap<>();
    private Holder() { }
}

private MyType(String name, Integer id) {
    this.name = name;
    this.id = id;
    Holder.idMap.put(id, this);
}

public String getName() {
    return name;
}

public static MyType byId(Integer id) {
    return Holder.idMap.get(id);
}

我可以扩展现有状态,而不是更改它吗?可以使用方法从数据库添加额外的IDS吗?

编辑

即使我更新为@StefanFischer建议使用接口填充枚举类和新数据库类的接口,我仍然希望代码中通过 select ID from TYPE 方法返回枚举,

byId

3 个答案:

答案 0 :(得分:6)

如果我理解正确,要求是:

  • 具有MyType.byId(Integer id)方法,该方法可提供一些预定义的值
  • 还应该从数据库的表Type中动态扩展它

所以一个枚举不能动态扩展,但是我们可以切换到一个类。

因此,紧贴您的代码可以写类似以下内容的

import java.util.HashMap;
import java.util.Map;

public class MyType {

    static Map<Integer, MyType> idMap = new HashMap<>();
    static {
        idMap.put(10, new MyType("First Type"));
        idMap.put(20, new MyType("Second Type"));
    }

    private final String name;

    private MyType(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public static MyType byId(Integer id) {
        return idMap.get(id);
    }

    public static void addType(String name, Integer id) {
        MyType lookup = byId(id);
        if(lookup != null) {
            if(!lookup.getName().equals(name)) {
                System.out.println("conflicting redefinition for id " + id + ": '" + name + "' vs '" + lookup.name + "'");
                //handle...
            }
        }
        idMap.put(id, new MyType(name));
    }
}

测试数据

假设数据库中包含以下内容:

stephan=# select * from Type;
 id |    name     
----+-------------
 30 | Third Type
 10 | First Type
 20 | Second Type
(3 rows)

因此在数据库中,我们具有id = 10和id = 20的预定义类型,还有id = 30的类型,默认情况下应用程序不知道。但是我们可以从数据库中填充类型。

测试用例

public static void main(String[] args) {
    try {
        Connection connection = createConnection();
        try (connection) {
            populateTypes(connection);
        }

        MyType type;

        type = MyType.byId(10);
        System.out.println(type.getName());

        type = MyType.byId(20);
        System.out.println(type.getName());

        type = MyType.byId(30);
        System.out.println(type.getName());

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

JDBC示例

使用哪种实际数据库技术检索值都没有关系。这是JDBC的示例:

private static void populateTypes(Connection connection)
        throws SQLException {

    String sql = "SELECT * FROM type";
    try (Statement st = connection.createStatement()) {
        try (ResultSet rs = st.executeQuery(sql)) {
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                MyType.addType(name, id);
            }
        }
    }
}

演示输出

First Type
Second Type
Third Type

您正在寻找什么吗?

答案 1 :(得分:5)

一个独特的非答案:您正试图将自己逼入错误的兔子洞。

枚举的整体要点是在编译时为您提供某些优势。在运行时,如果您有一个包含一些final static Whatever字段的类,或者是一个具有不同常量的Enum,则对JVM而言实际上并不重要。或者,如果您将EnumSet与普通的Set相对使用。

之所以使用枚举,是因为它们允许您以更优雅的方式写下 source 代码。

因此,在运行时进行生成枚举的方法没有意义。

枚举的想法是您使用它们编写 source 代码。但是,当为您生成枚举时,您将如何利用它们精确编写源代码?如前所述,默认情况下,枚举类是final。您不能单独扩展或增强它们。无论您想要拥有什么,都需要为您生成。再次提出了一个问题:您将如何在编译时利用运行时生成的东西?

因此,从概念的角度来看,另一个答案(使用Map)中概述的方法比试图将枚举转化为它们不是的枚举要好得多。应该是。

答案 2 :(得分:1)

枚举表示一组常量(不可更改的变量,如最终变量)。您不能在运行时定义它。