JDBC返回空结果集

21

我正在使用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;
    }

}

我目前已经硬编码了查询,以消除错误的来源。和之前一样的问题(这种情况发生在所有查询中)。调试器显示所有对象都被实例化,没有打印堆栈跟踪信息。此外,我能够在另一个项目中使用相同的代码(包括之前列出的更复杂的代码)。


1
请发布您的代码。没有代码,这里就没有足够的信息来提供答案。 - Asaph
如果您能够发布getResults函数的内容,那么它可能就在该函数内部。这将非常有帮助。 - Brains1994
1
你确定你的 connectionStringuserpassword 都是正确的吗? - darioo
16个回答

27

我明白了......可恶的Oracle不喜欢我有太多并发连接 (只有两个,一个是控制台,一个是Java)。不幸的是,服务器不在我的控制之下,所以我只能处理它。你会认为Oracle会提供更好的响应,但它只返回空结果集。

感谢回复。

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


“一个是控制台,一个是Java”,听起来很奇怪! - craftsman
是的,我已经使用SSH登录到主机上,直接运行查询以进行测试。当我运行我的程序时,它创建了另一个连接。如果我的措辞听起来很奇怪,抱歉。昨晚处理这个问题时我非常困倦。 - dpsthree
四年后我又遇到了同样的问题。非常感谢你,是的,Oracle 真是太蠢了。 - fleetC0m

9
同样的情况也发生在我身上。 我使用SQL Developer将测试数据插入到我的数据库中,并使用JDBC进行测试读取。 但是我得到的只是一个空结果集。 我可以得到列名等所有内容,但是在读取数据时出现了问题。正如dpsthree之前指出的那样,我断开了与SQL Developer IDE的连接,然后退出时它要求我提交更改。
唰! 问题在于使用插入命令对数据库进行的更改并没有提交。
对于SQL Developer,这位于“首选项>数据库>高级>自动提交”。
这解决了我的问题。

9

我看到你的代码中存在一些问题,有几个地方可能会出错:

首先,使用常规语句。请使用预处理语句,这样就不会遇到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
在java.sql.connection中,您应该在创建连接后调用此方法:
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);

也许在Oracle中有类似的方法。

3

过去我在类似于这样的代码中遇到了类似的问题:

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
}

在这种情况下,我将所有数据加载到本地内存数据结构中,最小化等待结果集。然后在优雅地关闭结果集后,对来自本地数据结构的数据进行必要的操作。这种行为是在Oracle 10的Unix后端/JDK 1.6.0_22客户端下的Windows XP上实现的。希望这能有所帮助。

3

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

desc table;
select * from sometable where etc.;

对于不返回结果的语句,您需要使用不同的结构。即使这样也会导致客户端出现问题:

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

两个形状相同的结果集将会让客户端出现错误。

2

是的,我和OP一样遇到了同样的问题。当您在同一用户上有两个或更多打开的与数据库的连接时,就会出现这种情况。例如,在SQL Developer中有一个连接,在Java中有一个连接。结果总是一个空结果集。

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


2

我随后在数据库中核对了查询语句(直接从调试器中复制),以确保其返回数据。

我曾经见过遇到这个问题的工程师在我面前进行这种验证。结果发现,他们在程序中使用了一个数据库账号,在交互式SQL shell中使用了另一个数据库账号。[这是Oracle 8.]


1
我曾使用plsql客户端登录服务器,但在尝试从我的代码连接时,虽然成功连接,但结果集中没有记录。只有在退出服务器后,结果集才被填充。我同意@dpsthree的观点,Oracle应该提供适当的错误/警告信息。

1
请在迭代结果集之前检查连接和语句对象是否仍然存在,有时我们可能会不知情地关闭它们。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接