JDBC возвращает пустой набор результатов - PullRequest
16 голосов
/ 03 декабря 2010

Я использую JDBC для очень простого подключения к базе данных.

Я создал свое соединение / оператор и выполнил запрос.Я проверяю объект запроса оператора в отладчике, чтобы убедиться, что он отправляет правильный запрос.Затем я дважды проверил запрос (скопированный прямо из отладчика) в базе данных, чтобы убедиться, что он возвращает данные.Однако возвращенный набор результатов дает false для .next ()

Есть ли здесь какие-либо распространенные ловушки, которые мне не хватает?

public List<InterestGroup> getGroups() {
    myDB.sendQuery("select distinct group_name From group_members where
            username='" + this.username + "'");
    ResultSet results = myDB.getResults();
    List<InterestGroup> returnList = new ArrayList<InterestGroup>();
    try {
        while (results.next()) {
            returnList.add(new InterestGroup(results.getString("group_name"), myDB));
        } 
        return returnList;
    } catch (SQLException e) {
        e.printStackTrace();
        return null;
    }

}

И класс myDB (простая оболочка, которая позволяет мнеперетащите код соединения / оператора в любой проект)

public void sendQuery(String query){
    this.query = query;
    try {
        if(statement == null){
            statement = connection.createStatement();
        }
        results = statement.executeQuery(query);
    } catch (SQLException e) {
        System.out.println(query);
        currentError = e;
        results = null;
        printError(e, "querying");
    }

}

public ResultSet getResults(){
    return results;
}

РЕДАКТИРОВАТЬ: Основываясь на предложениях, я в основном обновил свой код, но все еще остается та же проблема.Ниже приведен упрощенный фрагмент кода, в котором возникла та же проблема.

private boolean attemptLogin(String uName, String pWord) {

    ResultSet results;
    try{
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        connection =DriverManager.getConnection(connectionString,user,password);
        PreparedStatement statement = connection.prepareStatement("select username from users where username='testuser'");
        results = statement.executeQuery();
        if(results != null && results.next()){
            System.out.println("found a result");
            statement.close();
            return true;
        }
        System.out.println("did not find a result");
        statement.close();
        return false;
    }catch(SQLException e){
        e.printStackTrace();
        return false;
    }

}

На данный момент я также жестко закодировал существующий запрос, чтобы устранить этот источник ошибки.Та же проблема, что и раньше (это происходит со всеми запросами).Отладчик показывает, что все объекты создаются, а следы стека не печатаются.Кроме того, я могу использовать тот же код (и более сложный код, указанный выше) в другом проекте.

Ответы [ 14 ]

21 голосов
/ 03 декабря 2010

Я понял это ... тупому Оракулу не понравилось количество одновременных соединений, которые у меня были (все два из них, один для консоли, один для Java). К сожалению, сервер не находится под моим контролем, поэтому мне просто придется иметь дело с ним. Можно подумать, что Oracle даст лучший ответ. Вместо этого он просто возвратил пустые наборы результатов.

Спасибо за ответы

edit Поскольку этот вопрос был задан / получен ответ, многие люди указали, что основная причина, скорее всего, связана с используемыми настройками фиксации / транзакции. Обязательно посмотрите другие ответы для дополнительных советов и возможных решений.

9 голосов
/ 03 декабря 2010

Я вижу несколько ошибок в вашем коде, есть несколько мест, где все может пойти не так:

Во-первых, использование регулярных операторов. Используйте подготовленные операторы , чтобы у вас не было проблем с SQL-инъекцией .

Вместо

statement = connection.createStatement();

использование

statement = connection.prepareStatement(String sql);

С этим ваш запрос становится

"select distinct group_name From group_members where username= ?"

и вы устанавливаете имя пользователя с помощью

 statement.setString(1, username);

Далее, мне не нравится использование вашего myDB класса. Что делать, если результаты null? Вы не проверяете ошибки в вашем методе public List<InterestGroup> getGroups().

public void sendQuery(String query) мне кажется, что не должно быть void, но должно возвращаться ResultSet. Кроме того, ищите в сети правильные способы обработки исключений JDBC.

Также эта строка:

new InterestGroup(results.getString("group_name"), myDB)

Почему у вас есть myDB в качестве параметра?

Я бы предложил добавить в ваш код дополнительные операторы System.out.println, чтобы вы могли видеть, где что-то может пойти не так.

5 голосов
/ 19 июня 2011

В java.sql.connection вы должны вызывать этот метод после создания вашего соединения:

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

возможно, есть похожий метод в Oracle.

4 голосов
/ 18 декабря 2015

То же самое случилось со мной.Я использовал SQL Developer для вставки тестовых данных в мою базу данных и чтения тестов с использованием JDBC.Но все, что я получил, было пустым набором результатов.Я мог получить имена столбцов и все, но у меня была проблема с чтением данных.Как указывалось ранее в dpsthree, я отключился от среды разработки SQL Developer, а затем попросил выполнить коммит при выходе.

Вуаля!Проблема заключалась в том, что изменения в базах данных с помощью команды вставки не были зафиксированы.

Для SQL Developer это находится в Предпочтения> База данных> Дополнительно> Автокоммит

Это решило мою проблему.

3 голосов
/ 03 декабря 2010

Наиболее распространенным является наличие в запросе нескольких операторов:

desc table;
select * from sometable where etc.;

Для операторов, которые не возвращают результаты, вы должны использовать другую конструкцию.Даже это приведет к тому, что клиент захлебнется:

select * from sometable where whatever;
select * from sometable where something else;

Два набора результатов одинаковой формы будут раздражать клиента.

2 голосов
/ 29 сентября 2011

В прошлом у меня были подобные проблемы в коде, такие как этот:

querystr = "your sql select query string"

resultset = statement.executeQuery(querystr)

while (resultset.next())
{
//do something with the data. 
//if you do something fairly involved in this block (sequentially, in the same thread)
//such as calling a function that acts on the data returned from the resultset etc.
//it causes the resultset fetch to wait long enough for resultset.next() to 
//unexpectedly return null in the middle of everything
}

В этой ситуации я загружал все данные в структуру данных локальной памяти с минимальным ожиданием resultset.next().Затем я сделал все, что мне было нужно, с данными из локальной структуры данных после изящного закрытия набора результатов.Такое поведение было с Oracle 10 на клиенте бэкенда Unix / JDK 1.6.0_22 под Windows XP.

Надеюсь, это поможет.

2 голосов
/ 03 декабря 2010

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

У меня были инженеры с этой проблемой, демонстрирующие эту проверку передо мной.Оказывается, они вошли в систему с одной учетной записью базы данных в программе и с другой учетной записью базы данных в интерактивной оболочке SQL.[Это был Oracle 8.]

1 голос
/ 14 марта 2018

Возможно, ваша таблица не является зафиксированной . Попробуйте вставить новые записи, а затем зафиксировать в окне командной строки SQL Run и запустить свой код.

1 голос
/ 24 мая 2017

Я вошел на сервер с помощью клиента plsql, и, хотя я пытался подключиться из своего кода, я успешно подключался, но в наборе результатов не было записей. Только после выхода с сервера набор результатов был заполнен. Я согласен с @dpsthree, Oracle должен предоставить соответствующее сообщение об ошибке / предупреждение.

1 голос
/ 01 февраля 2017

Да, у меня была та же проблема, что и у ОП. Это происходит, когда у вас есть два или более открытых соединения с базой данных на одном и том же пользователе. Например, одно соединение в SQL Developer и одно соединение в Java. Результатом всегда является пустой набор результатов.

РЕДАКТИРОВАТЬ: Также я заметил, что это происходит, когда вы выполняете процедуру или вставляете в базу данных, и вы не фиксируете свои транзакции.

...