Enum представляет таблицу базы данных

У меня есть текущее состояние, когда enum MyType представляет таблицу типов со столбцами в виде:

ID
Name

И это используется для идентификации типа с помощью параметра 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);
}

Моим новым требованием является поддержка также значений в таблице типов, я нашел ответы для динамического перечисления, но принять ответ не для этого

Нет. Перечисления всегда фиксируются во время компиляции. Единственный способ сделать это - сгенерировать соответствующий байт-код динамически.

Что будет лучшим решением для поиска значений (в основном идентификаторов) из базы данных (например, идентификатор 30)

 select ID from TYPE

Могу ли я расширить существующее состояние вместо того, чтобы изменить его? я могу добавить дополнительные IDS из базы данных, используя метод?

РЕДАКТИРОВАТЬ

Даже если я обновлю, так как @StefanFischer предложил интерфейс, который заполняет карту классом enum и новым классом базы данных, я все равно ожидаю в коде возврата enum 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);
    }
}

0 ответов

Четкий отрицательный ответ: вы пытаетесь загнать себя не в ту кроличью нору.

Вся точка Перечисления должны дать вам определенные преимущества при компиляции времени. Во время выполнения для JVM не имеет значения, есть ли у вас класс с некоторымиfinal static Whateverполя или Enum с разными константами. Или если вы используетеEnumSet по сравнению с обычным Set.

Вы используете перечисления, потому что они позволяют более элегантно записывать исходный код.

Поэтому подход генерации перечислений во время выполнения не имеет смысла.

Идея перечислений заключается в том, что вы пишете исходный код, используя их. Но когда ваши перечисления будут генерироваться для вас, как именно вы бы написать исходный код эксплуатируя их?! Как уже упоминалось, классы перечисления по умолчанию являются окончательными. Вы не можете расширять или улучшать их по отдельности. Что бы вы ни хотели иметь, это должно быть создано для вас. И снова возникает вопрос: как бы вы использовали что-то во время компиляции, что генерируется во время выполнения?

Следовательно, с концептуальной точки зрения подход, изложенный в другом ответе (использование карты), является гораздо лучшей точкой проектирования, чем попытки превратить перечисления во что-то, чем они не должны быть.

If I understand it correctly the requirements are:

  • having a MyType.byId(Integer id) method that delivers some predefined values
  • it should be also extended dynamically from a Table Type from the database

So a enum can not be extended dynamically, but we could switch to a class.

So staying close to your code one could write something like:

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

Test Data

Let's assume we have the following in the database:

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

So in the database we have the predefined types with id=10 and id=20 but also a type with id=30 that is not known per default to the application. But we can populate the types from the database.

Test Case

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 Example

It doesn't matter what actual database technology is used to retrieve the values. Here an example for 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);
            }
        }
    }
}

Demo Output

First Type
Second Type
Third Type

Is that what you are looking for?

Enum представляет группу констант (неизменяемых переменных, таких как конечные переменные). вы не можете определить его во время выполнения.

Другие вопросы по тегам