JDBC 返回空结果集

发布于 2024-10-05 09:16:45 字数 2310 浏览 5 评论 0 原文

我使用 JDBC 来实现非常简单的数据库连接。

我已经创建了连接/语句并执行了查询。 我在调试器中检查语句的查询对象,以确认它正在发送正确的查询。 然后,我仔细检查数据库上的查询(直接从调试器复制)以确保它返回数据。 然而,返回的结果集在 .next() 上给出 false

是否有我遗漏的常见陷阱?

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

}

我现在还对查询进行了硬编码,以消除错误源。与以前相同的问题(所有查询都会发生这种情况)。调试器显示所有实例化的对象,并且不打印任何堆栈跟踪。此外,我可以在不同的项目中使用相同的代码(以及前面列出的更复杂的代码)。

I'm using JDBC for very simple database connectivity.

I have created my connection/statement and executed a query.
I check the query object of the statement in the debugger to confirm that it is sending a proper query.
I then double checked the query (copied straight from debugger) on the database to make sure it returns data.
The returned resultset, however, gives false on .next()

Are there any common pitfalls here that I'm missing?

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

}

And the myDB class (simple wrapper that lets me drop the connection/statement code into any project)

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:
Based on suggestions I have mostly revamped my code but still have the same problem. Below is a simplified portion of code that has the same problem.

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

}

I have also hardcoded the query in place for now to eliminate that source of error. Same problem as before (this happens with all queries). Debugger shows all objects getting instantiated and no stack traces are printed. Furthermore, I am able to use the same code (and the more complicated code listed previously) in a different project.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(16

如若梦似彩虹 2024-10-12 09:16:45

我发现了......愚蠢的Oracle不喜欢我拥有的并发连接数(所有两个,一个用于控制台,一个用于java)。不幸的是,服务器不在我的控制之下,所以我只能处理它。您可能认为 Oracle 会提供更好的回应。相反,它只返回空结果集。

感谢您的回复

编辑自从提出这个问题/回答以来,很多人指出根本原因更可能与使用的提交/事务设置有关。请务必查看其他答案以获得更多提示和可能的解决方案。

I figured it out....stupid Oracle didn't like the number of concurrent connections I had (all two of them, one for console, one for java). Unfortunately, the server is not under my control so I will just have to deal with it. You would think that Oracle would provide a better response. Instead it just returned empty result sets.

Thanks for the responses

edit Since this was asked/answered there have been a number of people pointed out that the underlying cause is more likely related to the commit/transaction settings in use. Please be sure to see other answers for additional hints and possible solutions.

牵强ㄟ 2024-10-12 09:16:45

我也遇到同样的情况。我使用 SQL Developer 将测试数据插入到我的数据库中,并使用 JDBC 测试读取该数据。但我得到的只是一个空的结果集。我可以获得列名称和所有内容,但在读取数据时遇到问题。正如 dps Three 之前指出的,我断开了与 SQL Developer IDE 的连接,然后它要求我在退出时提交。

瞧!问题是使用插入命令对数据库所做的更改未提交。

对于 SQL Developer,它位于首选项 >数据库>高级>自动提交

这解决了我的问题。

The same happened to me. I was using SQL Developer to insert test data into my database and test-reading that using JDBC. But all I got was an empty result-set. I could get the column names and all, but had a problem with reading data. As pointed out by dpsthree earlier, I disconnected from the SQL Developer IDE and then it asked me to Commit upon exiting.

Voila! The problem was that the changes to the databases using the insert command weren't committed.

For SQL Developer this is located at Preferences > Database > Advanced > Autocommit

This solved my problem.

半城柳色半声笛 2024-10-12 09:16:45

我在您的代码中发现了一些陷阱,有一些地方可能会出错:

首先,使用常规语句。使用准备好的语句,这样您就不会遇到SQL 注入。

而不是

statement = connection.createStatement();

使用

statement = connection.prepareStatement(String sql);

此,您的查询变成

"select distinct group_name From group_members where username= ?"

并使用

 statement.setString(1, username);

Next 设置用户名,我不喜欢使用您的 myDB 类。如果结果为 null 怎么办?您没有在您的 public List 中进行任何错误检查getGroups() 方法。

public void sendQuery(String query) 在我看来,它不应该是 void,但它应该返回一个 ResultSet。另外,请在网上搜索执行 JDBC 异常处理的正确方法。

另外,这一行:

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

为什么你有 myDB 作为参数?

我建议在代码中添加更多 System.out.println 语句,以便您可以看到哪里可能出错。

I see a few pitfalls in your code, there are a few places where things can go wrong:

First, use of regular statements. Use prepared statements so you won't have problems with SQL injection.

Instead of

statement = connection.createStatement();

use

statement = connection.prepareStatement(String sql);

With this, your query becomes

"select distinct group_name From group_members where username= ?"

and you set username with

 statement.setString(1, username);

Next, I don't like use of your myDB class. What if results is null? You're not doing any error checking for that in your public List<InterestGroup> getGroups() method.

public void sendQuery(String query) seems to me like it shouldn't be void, but it should return a ResultSet. Also, search on the net for proper ways to do JDBC exception handling.

Also, this line:

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

Why do you have myDB as a parameter?

I'd suggest adding more System.out.println statements in your code so you can see where things can go wrong.

感情废物 2024-10-12 09:16:45

在 java.sql.connection 中,您应该在创建连接后调用此方法:

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

也许 Oracle 中有类似的方法。

In java.sql.connection you should call this method after you create your connection :

conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

maybe there is a similar method in Oracle.

心碎无痕… 2024-10-12 09:16:45

最常见的是查询中有多个语句:

desc table;
select * from sometable where etc.;

对于不返回结果的语句,您必须使用不同的构造。即使这样也会导致客户端窒息:

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

两个相同形状的结果集会让客户端感到困惑。

The most common is having multiple statements in the query:

desc table;
select * from sometable where etc.;

For statements which do not return results, you have to use a different construct. Even this will cause the client to choke:

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

The two same-shaped result sets will biff the client.

情独悲 2024-10-12 09:16:45

过去,我在代码中遇到过类似的问题,如下所示:

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() 上等待最少的时间。然后,在优雅地关闭结果集后,我对本地数据结构中的数据做了任何我必须做的事情。此行为是在 Windows XP 下的 Unix 后端/JDK 1.6.0_22 客户端上的 Oracle 10 中出现的。

希望这有帮助。

In the past I had similar issues in code such as this:

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
}

What I did in this situation was to load up all data into a local memory data structure with minimum wait on resultset.next(). Then I did whatever I had to on the data from the local data structure after gracefully closing resultset. This behavior was with Oracle 10 on Unix backend/JDK 1.6.0_22 client under Windows XP.

Hope this helps.

〆凄凉。 2024-10-12 09:16:45

然后,我仔细检查了数据库上的查询(直接从调试器复制),以确保它返回数据。

我曾让遇到此问题的工程师在我面前演示过此验证。事实证明,他们在程序中使用一个数据库帐户登录,在交互式 SQL shell 中使用不同的数据库帐户登录。 [这是 Oracle 8。]

I then double checked the query (copied straight from debugger) on the database to make sure it returns data.

I've had engineers with this problem demonstrate this verification in front of me. It turns out they were logged in with one database account in the program and with a different database account in the interactive SQL shell. [This was Oracle 8.]

时光沙漏 2024-10-12 09:16:45

是的,我和OP有同样的问题。当同一用户与数据库有两个或多个打开的连接时,就会发生这种情况。例如,SQL Developer 中的一个连接和 Java 中的一个连接。结果始终是空结果集。

编辑:另外,我注意到当您执行过程或插入数据库并且不提交事务时会发生这种情况。

Yeah, I had the same problem as the OP. It happens when you have two or more open connections with the database on the same user. For example one connection in SQL Developer and one connection in Java. The result is always an empty resultset.

EDIT: Also, I noticed that it happens when you execute procedure or insert in the databse and you don't commit your transactions.

似狗非友 2024-10-12 09:16:45

请检查连接和语句对象是否存活,直到迭代结果集,有时我们可能会在不知不觉中关闭。

Please check whether the connection and statement Object alive until you iterate the result set, some times we may close unknowingly.

慕巷 2024-10-12 09:16:45

可能的情况是您的表未提交
尝试插入新记录,然后在 SQL 运行命令窗口中提交并运行代码。

It might be a condition that your table is not committed .
Try inserting new records, then commit in your SQL Run Command Window and run your code.

奢欲 2024-10-12 09:16:45

我已使用 plsql 客户端登录到服务器,并尝试从我的代码进行连接。

我连接成功,但结果集中没有记录。

仅在从服务器注销后,结果集才会被填充。

我同意@dps Three,Oracle 应该提供适当的错误/警告消息。

I had logged in to server using plsql client and while I tried to connect from my code.

I was successfully connecting but there were no records in the result-set.

Only after logging out from the server the result-set was populated.

I agree with @dpsthree, Oracle should provide appropriate error/warning message.

这样的小城市 2024-10-12 09:16:45

对我来说,问题是在创建主键列时我没有启用 NOT NULL。正如......

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 驱动程序。

For me the problem was that on the creation of the primary key column I had NOT NULL ENABLE. As in ...

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;

When I recreated the table without that as in

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;

It started working via JDBC. I am using ojdbc6.jar for the jdbc driver.

不疑不惑不回忆 2024-10-12 09:16:45

即使您应该获取查询的行值,resultSet也会返回 false,并且 rs.next() 给出 false,因为您可能没有在查询的 sql 终端上编写 commit; 。执行此操作后,您将得到 rs.next() 为 True。

The resultSet returns false even though you should get row values for the query and rs.next() gives false because you might have not written commit; on your sql terminal for the query. After doing this you will get rs.next() as True.

我最亲爱的 2024-10-12 09:16:45

这是因为输入的数据不会保存在表中。
将值插入表后,只需提交表即可。这与我们文件系统中的保存选项类似。

This is because the data entered will not be save in the table.
Just commit the table once the values are inserted in the tables. This acts similar to save option in our file system.

摇划花蜜的午后 2024-10-12 09:16:45

我也遇到同样的情况。我使用 SQL Developer 将测试数据插入到我的数据库中,并使用 JDBC 测试读取该数据。但我得到的只是一个空的结果集。我可以获得列名称和所有内容,但在读取数据时遇到问题。正如 dps Three 之前指出的,我断开了与 SQL Developer IDE 的连接,然后它要求我在退出时提交。

瞧!问题是使用插入命令对数据库所做的更改未提交。

对于 SQL Developer,它位于“首选项”>“数据库>高级>自动提交

这解决了我的问题。

The same happened to me. I was using SQL Developer to insert test data into my database and test-reading that using JDBC. But all I got was an empty result-set. I could get the column names and all, but had a problem with reading data. As pointed out by dpsthree earlier, I disconnected from the SQL Developer IDE and then it asked me to Commit upon exiting.

Voila! The problem was that the changes to the databases using the insert command weren't committed.

For SQL Developer this is located at Preferences > Database > Advanced > Autocommit

This solved my problem.

忘年祭陌 2024-10-12 09:16:45

就我而言,在 sql Developer 中有效的查询在 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'*

in my case the query which worked in sql developer didn't work in JAVA.

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

formating process_date to char helped to make it work in JAVA

*select * from table where to_char(process_date) = '06-AUG-14'*
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文