Как проверить, существует ли имя столбца в CachedRowSet?
Я запрашиваю данные из представлений, которые могут быть изменены. Мне нужно знать, существует ли столбец, прежде чем я сделаю crs.get******()
Я обнаружил, что могу запросить метаданные, например, чтобы увидеть, существует ли столбец, прежде чем запрашивать у него данные.
ResultSetMetaData meta = crs.getMetaData();
int numCol = meta.getColumnCount();
for (int i = 1; i < numCol+1; i++)
if(meta.getColumnName(i).equals("name"))
return true;
Есть ли более простой способ проверить, существует ли столбец?
РЕДАКТИРОВАТЬ: Это должно быть независимым от базы данных. Вот почему я ссылаюсь на CachedRowSet
вместо базы данных.
6 ответов
Там нет более простого способа с общим API JDBC (по крайней мере, я не знаю, или не могу найти... У меня точно такой же код в моем собственном наборе инструментов).
(Ваш код не завершен):
ResultSetMetaData meta = crs.getMetaData();
int numCol = meta.getColumnCount();
for (int i = 1; i < numCol+1; i++)
{
if(meta.getColumnName(i).equals("name"))
{return true;}
}
return false;
Тем не менее, если вы используете проприетарные, специфичные для базы данных API-интерфейсы и / или SQL-запросы, я уверен, что вы можете найти более элегантные способы сделать то же самое... но вам придется писать собственный код для каждой базы данных, которую вы надо иметь дело с. Я бы придерживался API JDBC, если бы вы были вами.
Есть ли что-то в предложенном вами решении, которое заставляет вас думать, что оно неверное? Это кажется мне достаточно простым...
Вы могли бы использовать более короткий подход, используя тот факт, что findColumn() сгенерирует исключение SQLEx для InvalidColumName, если столбец отсутствует в CachedRowSet.
например
try {
int foundColIndex = results.findColumn("nameOfColumn");
} catch {
// do whatever else makes sense
}
Вероятно злоупотребление обработкой исключений (согласно EffectiveJava 2nd ed item 57), но это альтернатива циклическому прохождению всех столбцов из метаданных.
Какая база данных?
Я думаю, что в Oracle есть таблицы, в которых перечислены столбцы.
Я не помню, работает ли это также и для представлений, но я думаю, что они работают, это было что-то вроде:
select colum_name from all_views where view_name like 'myview'
или же
select name from all_objects where object_name like 'myview' and object_type='view'
Я не помню точно синтаксис. Вы должны иметь пространственные разрешения, хотя.
Каждая СУБД должна иметь что-то похожее.
Вы также можете выполнить запрос
select * from myView where 1 = 0 ;
А из метаданных получите столбцы, если хотите, чтобы они не извлекали данные, прежде чем узнать, присутствуют ли столбцы.
Нет, лучшего способа нет. Вы можете пересмотреть проблему. Если вы можете переопределить проблему, иногда это упрощает решение, потому что проблема изменилась.
ВНИМАНИЕ: следующий комментарий чисто из памяти без каких-либо сопроводительных документов:)
Если я правильно помню, есть таинственная проблема, которая поднимает свою безобразную голову, когда реализация набора кэшированных строк оракула используется с пулами соединений. Похоже, что есть неявная ссылка на соединение, хранящееся в кэшированном объекте набора строк (даже если он должен быть отключен), который закрывает другое соединение, впоследствии открытое из пула при сборке мусора. По этой причине я в конце концов сдался и написал свой собственный слой объектов данных (в наши дни я передаю его в весенний и спящий режим).
Старый поток, но я только что столкнулся с той же проблемой и в итоге получил служебную функцию:
private Set<String> getColumnNames(ResultSet cached) throws SQLException {
ResultSetMetaData metaData = cached.getMetaData();
return IntStream.range(1, metaData.getColumnCount())
.mapToObj(i -> {
try {
return metaData.getColumnName(i);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}).collect(toSet());
}
Было бы довольно элегантно, если бы нам не приходилось ловить исключения внутри лямбды (без каких-либо уродливых хаков)
Продолжая главный ответ в этой беседе от Джареда и один из недооцененных комментариев от corsiKa:
ResultSetMetaData meta = crs.getMetaData();
int numCol = meta.getColumnCount();
Set<String> columns = new HashSet<>;
for (int i = 1; i <= numCol; i++)
{
columns.add(meta.getColumnName(i));
}
return columns.contains("name");