Как проверить, существует ли имя столбца в CachedRowSet? - PullRequest
9 голосов
/ 20 января 2009

Я запрашиваю данные из представлений, которые могут быть изменены. Мне нужно знать, существует ли столбец до того, как я сделаю 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;

Есть ли более простой способ проверить, существует ли столбец?

EDIT: Это должно быть независимым от базы данных. Вот почему я ссылаюсь на CachedRowSet вместо базы данных.

Ответы [ 6 ]

8 голосов
/ 27 января 2011

Вы можете использовать более короткий подход, используя тот факт, что findColumn () сгенерирует SQLException для InvalidColumName, если столбец отсутствует в CachedRowSet.

например

 try {
     int foundColIndex = results.findColumn("nameOfColumn");
} catch {
  // do whatever else makes sense
}

Вероятно, злоупотребление обработкой исключений (согласно EffectiveJava, 2-е изд, пункт 57), но это альтернатива циклическому прохождению всех столбцов из метаданных.

8 голосов
/ 20 января 2009

Нет более простого способа с общим 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, если бы вы были вами.

Есть ли что-то в предложенном вами решении, которое заставляет вас думать, что оно неверное? Это кажется мне достаточно простым ...

1 голос
/ 20 января 2009

Нет, лучшего способа нет. Вы можете пересмотреть проблему. Если вы можете переопределить проблему, иногда это упрощает решение, поскольку проблема изменилась.

1 голос
/ 20 января 2009

Какая база данных?

Я думаю, что в 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 ; 

А из метаданных получите столбцы, если хотите, чтобы они не выбирали данные, прежде чем узнать, присутствуют ли столбцы.

0 голосов
/ 07 июня 2018

Старый поток, но я только что столкнулся с той же проблемой и в итоге получил служебную функцию:

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

Было бы неплохо, если бы нам не приходилось ловить исключения внутри лямбды (без каких-либо уродливых хаков)

0 голосов
/ 08 октября 2009

ВНИМАНИЕ: следующий комментарий чисто из памяти без каких-либо сопроводительных документов:)

Если я правильно помню, существует загадочная проблема, которая поднимает свою безобразную голову, когда реализация набора кэшированных строк оракула используется с пулами соединений. Похоже, что есть неявная ссылка на соединение, хранящееся в кэшированном объекте набора строк (даже если он должен быть отключен), который закрывает другое соединение, впоследствии открытое из пула при сборке мусора. По этой причине я в конце концов сдался и написал свой собственный слой объектов данных (в эти дни я бы передал это в spring & hibernate).

...