带资源尝试的 JDBC

Posted

技术标签:

【中文标题】带资源尝试的 JDBC【英文标题】:JDBC with try with resources 【发布时间】:2016-07-19 18:06:18 【问题描述】:

我正在尝试创建一个集中类来连接并返回 SQL 查询的 ResultSet,这样我就不必每次尝试获取查询时都创建新连接。

我正在使用try-with-resources,但是,每当我使用try-with-resources 时都会出现编译时错误,我不知道为什么?

public class JDBC 

    // logger declaration is omitted

    private static final String dbURL = "jdbc:oracle:";
    private static final String userName = "blah";
    private static final String password = "12345";

    public ResultSet retrieveSQLQuery(String sqlQuery)             
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;

        try (conn = DriverManager.getConnection(dbUrl, user, password);
             statement = conn.createStatement();
             rs = statement.executeQuery(sqlQuery))                

         catch (SQLException e) 
            logger.info(e.getMessage());
                            
        return rs;        
    

【问题讨论】:

错误是什么? @AlexandruMarina 我遇到了很多错误。一旦在 getConnection 上显示 unknown class collectionunhandle sql exception statement.executeQuery(sqlQuery) 您在关闭后返回一个结果集。这行不通。 @NathanHughes 嗯,那么我怎样才能创建一个可以从 sql 查询动态返回值的 jdbc 类?例如,如果我想查询一个 clob 而不是一个字符串?我不是必须返回一个 ResultSet 吗? 可能你的JDBC 类应该返回一个对象或集合,然后是来自ResultSet 的数据并关闭然后连接。 【参考方案1】:

Java 7

当您使用try-with-resources 时,指向Closeable 资源的变量必须在try-with-resources 块内声明

此外,返回rs 是个坏主意,它会在方法完成后关闭。所以你可能会在你的方法之外得到一个SQLException(类似于“ResultSet is closed”)。您应该在 try-with-resources 块内解析 rs 并从您的方法返回 SQL 不可知对象:

public ResultSet retrieveSQLQuery(String sqlQuery)             
    try (Connection conn = DriverManager.getConnection(dbUrl, user, password);
         Statement statement = conn.createStatement();
         ResultSet rs = statement.executeQuery(sqlQuery)) 
        MyResult result = ...; // parse rs here
        return myResult;               
     catch (SQLException e) 
        logger.info(e.getMessage());
        // return something (empty MyResult or null) from here or rethrow the exception
        // I'd recommend to get rid of this catch block and declare the SQLException on method signature
                        

您在不正确的try-with-resources 语法上遇到编译时错误,就是这样。


更新

Java 9 Java 9 为try-with-resources 提供了更灵活的语法。您可以在try (...) 块之外声明Closeable 资源:

public ResultSet retrieveSQLQuery(String sqlQuery) 
    Connection conn = DriverManager.getConnection(dbUrl, user, password);
    try (conn; ResultSet rs = conn.createStatement().executeQuery(sqlQuery)) 
        MyResult result = ...; // parse rs here
        return myResult;               
     catch (SQLException e) 
        // handle error
                        

【讨论】:

我明白了。嗯,但是我不能返回 rs 因为它不在范围内。但是,我只是被告知我不应该返回结果集 已编辑,您应该从try-block 返回 嗯,但是当我从 try 块返回时,我仍然得到一个编译错误 哦,是因为catch块,见更新。最好将你的方法声明为throws SQLException 并在外面捕获。 添加了更多编辑,返回 rs 是个坏主意,请参阅更新的答案。【参考方案2】:

你应该这样使用它:

   public ResultSet retrieveSQLQuery(String sqlQuery)             
        Connection conn = null;
        Statement statement = null;
        ResultSet rs = null;

        try       
            conn = DriverManager.getConnection(dbUrl, user, password);
            statement = conn.createStatement();
            rs = statement.executeQuery(sqlQuery);         
         catch (SQLException e) 
            logger.info(e.getMessage());
                             
        return rs; 
    

它不起作用,因为你把代码放在括号里。你应该把它放在这些括号里 -> 。这也是显示错误的原因,因为没有类的方法如下:

    try(bla bla bla) 

【讨论】:

OP 明确要求 try-with-resources 语法。你应该去阅读最新的语言手册。

以上是关于带资源尝试的 JDBC的主要内容,如果未能解决你的问题,请参考以下文章

从 JDBC 源迁移数据时如何优化分区?

kafka JDBC源连接器无法获取postgres表

具有动态查询的 Jdbc 消息源的 Spring 集成流

我可以从 JDBC 连接运行“源”命令(SQL 脚本)吗?

使用 JDBC 在 Oracle 数据库上创建 Java

Oracle JDBC Clob 插入问题 ORA-00942