use*_*900 -3 java enums database-driven
我有一个当前状态,其中enumMyType表示类型表,其列为:
ID
Name
Run Code Online (Sandbox Code Playgroud)
并使用ID参数和byId方法来识别类型:
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);
}
Run Code Online (Sandbox Code Playgroud)
我的新要求是支持Type表中也存在值,我找到了动态枚举的答案,但是接受答案不是这样做
否。枚举始终固定在编译时。您执行此操作的唯一方法是动态生成相关的字节码。
从数据库(例如ID 30)中查找值(主要是ID)的更好解决方案是什么
select ID from TYPE
Run Code Online (Sandbox Code Playgroud)
我可以扩展现有状态而不是更改它吗?如何使用方法从数据库添加额外的IDS?
编辑
即使我更新为@StefanFischer建议使用接口填充枚举类和新数据库类的接口,我仍然希望代码中的枚举按byId方法返回,
public interface MyType {
public static class Holder {
static Map<Integer, MyType> idMap = new HashMap<>();
private Holder() { }
}
public default void add(MyType myType, Integer id) {
Holder.idMap.put(id, myType);
}
public static MyType byId(Integer id) {
return Holder.idMap.get(id);
}
}
Run Code Online (Sandbox Code Playgroud)
如果我正确理解的要求是:
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));
}
}
Run Code Online (Sandbox Code Playgroud)
测试数据
假设数据库中包含以下内容:
stephan=# select * from Type;
id | name
----+-------------
30 | Third Type
10 | First Type
20 | Second Type
(3 rows)
Run Code Online (Sandbox Code Playgroud)
因此,在数据库中,我们具有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();
}
}
Run Code Online (Sandbox Code Playgroud)
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);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
演示输出
First Type
Second Type
Third Type
Run Code Online (Sandbox Code Playgroud)
那是您要找的东西吗?
一个明显的非答案:您正试图将自己逼入错误的兔子洞。
枚举的全部要点是在编译时为您提供某些优势。在运行时,如果您有一个包含某些final static Whatever字段的类或一个具有不同常量的Enum,则对JVM而言实际上并不重要。或者,如果您使用EnumSetvs普通Set。
之所以使用枚举,是因为它们允许您以更优雅的方式写下源代码。
因此,在运行时生成枚举的方法没有意义。
枚举的想法是您使用它们编写源代码。但是,当为您生成枚举时,您将如何利用它们精确编写源代码?如前所述,默认情况下,枚举类是final。您不能单独扩展或增强它们。无论您想要拥有什么,都需要为您生成。这又引发了一个问题:您将如何在编译时利用在运行时生成的东西?
因此,从概念的角度来看,另一个答案(使用Map)中概述的方法比试图将枚举转化为不想要的枚举要好得多。
| 归档时间: |
|
| 查看次数: |
373 次 |
| 最近记录: |