JDBC возвращает пустой набор результатов

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

Я создал свой оператор connection/и выполнил запрос. Я проверяю объект запроса инструкции в отладчике, чтобы подтвердить, что он отправляет правильный запрос. Затем я дважды проверял запрос (скопированный прямо из отладчика) в базе данных, чтобы убедиться, что он возвращает данные. Однако возвращенный набор результатов дает значение 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;
}

EDIT: Основываясь на предложениях, я в основном обновил свой код, но все еще имею ту же проблему. Ниже приведена упрощенная часть кода, которая имеет ту же проблему.

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

}

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

Ответы

Ответ 1

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

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

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

Ответ 2

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

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

Вместо

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, чтобы вы могли видеть, где все может пойти не так.

Ответ 3

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

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

возможно, в Oracle существует аналогичный метод.

Ответ 4

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

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

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

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

Ответ 5

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

desc table;
select * from sometable where etc.;

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

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

Два одинаковых результирующих набора будут бифицировать клиента.

Ответ 6

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

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

Ответ 7

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

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 backend/JDK 1.6.0_22 под Windows XP.

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

Ответ 8

Пожалуйста, проверьте, жив ли объект соединения и оператора, пока вы не выполните итерацию результирующего набора, иногда мы можем закрыться неосознанно.

Ответ 9

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

EDIT: Кроме того, я заметил, что это происходит, когда вы выполняете процедуру или вставляете в базу данных, и вы не совершаете транзакции.

Ответ 10

Я вошел на сервер с помощью клиента plsql и попытался подключиться из своего кода.

Я успешно подключался, но в наборе результатов не было записей.

Только после выхода с сервера набор результатов был заполнен.

Я согласен с @dpsthree, Oracle должен предоставить соответствующее сообщение об ошибке/предупреждение.

Ответ 11

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

Ответ 12

в моем случае запрос, который работал в sql-разработчике, не работал в JAVA.

*select * from table where process_date like '2014-08-06%'* (worked in sql developer)

формирование process_date до char помогло заставить его работать в JAVA

*select * from table where to_char(process_date) = '06-AUG-14'*

Ответ 13

Для меня проблема заключалась в том, что при создании столбца первичного ключа у меня не было NULL ENABLE. Как в...

CREATE TABLE SYSTEM_SETTINGS  ( 
  SYSTEM_SETTING_ID NUMBER(9,0) NOT NULL ENABLE, 
    "KEY" VARCHAR2(50 BYTE), 
    "VALUE" VARCHAR2(128 BYTE),
     CONSTRAINT "PK_SYSTEM_SETTINGS" PRIMARY KEY (SYSTEM_SETTING_ID)) 
TABLESPACE USERS;

Когда я воссоздал таблицу без этого, как в

CREATE TABLE SYSTEM_SETTINGS  ( 
  SYSTEM_SETTING_ID NUMBER(9,0), 
    "KEY" VARCHAR2(50 BYTE), 
    "VALUE" VARCHAR2(128 BYTE),
     CONSTRAINT "PK_SYSTEM_SETTINGS" PRIMARY KEY (SYSTEM_SETTING_ID)) 
TABLESPACE USERS;

Он начал работать через JDBC. Я использую ojdbc6.jar для драйвера jdbc.

Ответ 14

Результирующий набор возвращает false, даже если вы должны получить значения строк для запроса, а значение rs.next() дает false, потому что вы, возможно, не указали commit; на свой SQL-терминал для запроса. После этого вы получите rs.next() как True.