结果集 NullPointerException

Posted

技术标签:

【中文标题】结果集 NullPointerException【英文标题】:ResultSet NullPointerException 【发布时间】:2013-05-12 09:09:39 【问题描述】:

我有一个存储过程,我想从 JDBC 中调用它,我的行中有空指针异常"

while (restuls.next()) 

我的代码是:

Connection con = Database.getConnection();
            CallableStatement callableStatement = null;
            try 
                String storedProcedure = "call getAllCustomerAddresses(?,?,?,?,?,?,?)";
                callableStatement = con.prepareCall(storedProcedure);
                callableStatement.setInt(1, this.getID());
                callableStatement.registerOutParameter(2,
                        java.sql.Types.INTEGER);
                callableStatement.registerOutParameter(3,
                        java.sql.Types.VARCHAR);
                callableStatement.registerOutParameter(4,
                        java.sql.Types.INTEGER);
                callableStatement.registerOutParameter(5,
                        java.sql.Types.INTEGER);
                callableStatement.registerOutParameter(6,
                        java.sql.Types.INTEGER);
                callableStatement.registerOutParameter(7,
                        java.sql.Types.VARCHAR);
                callableStatement.execute();
                System.out.println(callableStatement.getInt(2));
                System.out.println(callableStatement.getString(3));
                System.out.println(callableStatement.getInt(4));
                System.out.println(callableStatement.getInt(5));
                System.out.println(callableStatement.getInt(6));
                System.out.println(callableStatement.getString(7));
                ResultSet restuls = callableStatement.getResultSet();
                while (restuls.next()) 
                    int addressID = restuls.getInt(2);
                    String label = restuls.getString(3);
                    int regionID = restuls.getInt(4);
                    int areaID = restuls.getInt(5);
                    int cityID = restuls.getInt(6);
                    String description = restuls.getString(7);
                    this.addresses.add(new CustomerAddressImpl(this, label,
                            description, RegionImpl.getInstance(regionID),
                            AreaImpl.getInstance(areaID), CityImpl
                                    .getInstance(cityID), addressID));
                

查看代码,System.out.println 正在工作,它正在从数据库中打印正确的值,那么为什么结果集为空??

另外,我必须使用结果集,因为存储过程返回很多行。

我真的很困惑为什么我可以打印正确的值但结果集为空

提前致谢

编辑

如果你想给你存储过程请告诉我

存储过程

ALTER PROCEDURE [dbo].getAllCustomerAddresses(
@customerID INT,
@addressID INT OUTPUT,
@label VARCHAR(200) OUTPUT,
@regionID INT OUTPUT,
@areaID INT OUTPUT,
@cityID INT OUTPUT,
@description TEXT OUTPUT
)
AS
    SET NOCOUNT Off;
SELECT     @addressID = [ID],
@label = [label],
@regionID = [regionID],
@areaID = [areaID],
@cityID = [cityID],
@description = [description]
FROM  Customer_Address
WHERE customerID = @customerID

【问题讨论】:

“如果你想给你存储过程,请告诉我” 不,谢谢。为了尽快获得更好的帮助,请发帖SSCCE。 你确定 this.getID() 正在返回一些数据 @Satya yes ofc,有证据表明打印方法运行良好 @home 我的存储过程只是select,没有更新 restuls 应该是results :) 【参考方案1】:

PreparedStatementexecute() 方法如果结果集存在则返回true,否则返回false。您不检查execute() 的返回值。我认为如果你这样做,你就会发现它是错误的。

原因应该是在您的存储过程中恕我直言不返回值。因此,请尝试分析它以了解问题所在。

以下是我可以给你的建议:

    使用executeQuery() 直接返回ResaultSet 而不是execute()。我觉得这样更方便。 避免使用将独立于平台的 Java 代码与特定类型的数据库耦合的存储过程。尝试用 Java 编写所有逻辑并仅使用可移植的 SQL 语句。 我最后一次看到纯 JDBC 代码大约是在 10 年前。有很多工具可以帮助您避免在 Java 代码中编写 SQL。看看 JPA、Hibernate、iBatis 等。

【讨论】:

这并不完全正确,如果第一个/当前结果是 ResultSetexecute() 返回 true,如果是更新计数,则返回 false。在这里查看我的答案以获得更详细的解释:***.com/questions/14213824/… 我会试试你的答案,对于你最后的建议,我真的尽量避免在 java 逻辑中使用 sql,这就是我使用存储过程的原因,请告诉我如何让我的 java 独立于我的sql,谢谢【参考方案2】:

您的存储过程实际上并没有生成 ResultSet,因为您使用的是输出参数(不是 100% 确定,我没有方便测试的 SQL Server)。

您可能只需要调用CallableStatement.getObject(int)CallableStatement.getObject(String)(或特定类型的getter)来获取值。如果要处理为ResultSet,则不应在存储过程中使用输出参数,而应将存储过程编写为选择而不分配给输出参数。这将从存储过程中创建一个结果集

另一种可能性可能是您的存储过程在返回结果集之前首先返回一个或多个更新计数。 execute() 的布尔返回值指示第一个结果是更新计数还是ResultSet。您需要反复调用getMoreResults()getUpdateCount() 以确保您已处理所有结果。

您发布的存储过程包含SET NOCOUNT OFF,它向 SQL Server(或 Sybase)发出信号,您希望更新(我相信选择)计数也返回,您可能想尝试使用 SET NOCOUNT ON

您也可以尝试像这样处理execute()的结果,以确定结果集之前是否确实存在多个更新计数等:

boolean result = pstmt.execute();
while(true)
    if (result) 
        ResultSet rs = pstmt.getResultSet();
        // Do something with resultset ...
     else 
        int updateCount = pstmt.getUpdateCount();
        if (updateCount == -1) 
            // no more results
            break;
        
        // Do something with update count ...
    
    result = pstmt.getMoreResults();

另见Java SQL: Statement.hasResultSet()?

【讨论】:

我的存储过程中没有更新,请检查我的编辑答案,我放了存储过程 @MarcoDinatsoli 这并不重要 afaik,SQL Server 将根据 SET NOCOUNT 的文档为存储过程中的每个语句发送一个“受影响的行”计数:"SET NOCOUNT ON 防止为存储过程中的每个语句向客户端发送 DONE_IN_PROC 消息" @MarcoDinatsoli 另请参阅我的最新添加;可能只是您的存储过程没有生成结果集。 我试过你的代码,它给了我一个空的结果,不是空的,而是空的,但我看到了表格,它绝对有结果,正如我告诉你的,我可以打印它们,我把它“打开” " 而不是 "off",它仍然是一样的,

以上是关于结果集 NullPointerException的主要内容,如果未能解决你的问题,请参考以下文章

SQL 操作结果集 -并集差集交集结果集排序

SQL 操作结果集 -并集差集交集结果集排序

将List进行分组后结果返回Map结果集

如何保持结果集打开,或调用不同的结果集?

使用一个结果集创建不同的结果集[关闭]

数据访问设计:多个结果集单个存储过程或每个存储过程单个结果集