Заполните перечисление значениями из базы данных
-
21-08-2019 - |
Вопрос
У меня есть таблица, которая отображает String-> Integer.
Вместо того, чтобы создавать перечисление статически, я хочу заполнить перечисление значениями из базы данных.Возможно ли это ?
Итак, вместо того, чтобы распределять это статически:
public enum Size { SMALL(0), MEDIUM(1), LARGE(2), SUPERSIZE(3) };
Я хочу создать это перечисление динамически, поскольку числа {0,1,2,3} в основном случайны (потому что они автоматически генерируются столбцом АВТОИНКРЕМЕНТА базы данных).
Решение
Нет.Перечисления всегда фиксируются во время компиляции.Единственный способ, которым вы могли бы это сделать, - это динамически сгенерировать соответствующий байт-код.
Сказав это, вам, вероятно, следует разобраться, какие аспекты перечисления вас действительно интересуют.Предположительно, вы не хотели использовать switch
оператор над ними, поскольку это означало бы статический код, а вы не знаете значения статически...аналогично любым другим ссылкам в коде.
Если вам действительно просто нужна карта из String
Для Integer
, вы можете просто использовать Map<String, Integer>
который вы заполняете во время выполнения, и все готово.Если вы хотите, чтобы EnumSet
особенности, их было бы несколько сложнее воспроизвести с той же эффективностью, но это может быть осуществимо при определенных усилиях.
Итак, прежде чем идти дальше в плане размышлений о реализации, я предлагаю вам разобраться, каковы ваши реальные требования.
(РЕДАКТИРОВАТЬ:Я предполагал, что это перечисление полностью динамично, т.е.что вы не знаете ни названий, ни даже количества существующих значений.Если набор имен фиксирован и вы Только нужно извлечь идентификатор из базы данных, это совсем другое дело - см. Ответ Андреаса.)
Другие советы
Это немного сложно, поскольку заполнение этих значений происходит во время загрузки класса.Таким образом, вам понадобится статический доступ к подключению к базе данных.
Как бы я ни ценил его ответы, я думаю, что Джон Скит, возможно, на этот раз ошибается.
Взгляните на это:
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;
}
}
Совершенствуясь в что сделал Андреас, вы можете загрузить содержимое базы данных в карту, чтобы уменьшить количество необходимых подключений к базе данных.
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); }
}
}
Перечисления не являются динамическими, поэтому короткий ответ заключается в том, что вы не можете этого сделать.
Также взгляните на вопрос о переполнении стека Динамическое перечисление в C#.
Вам нужно реплицировать в коде то, что есть в базе данных (или наоборот).Видишь это вопрос за несколько хороших советов.
На всех известных мне языках перечисления статичны.Компилятор может внести в них некоторые изменения.Поэтому короткий ответ - нет, вы не можете.
Вопрос в том, почему вы хотите использовать перечисление таким образом.Чего ты ожидал?Или, другими словами, почему бы вместо этого не использовать коллекцию?