在单个方法中重用连接对象

时间:2018-09-12 19:23:43

标签: java jdbc

我遇到过这种模式。需要多个SQL语句执行时,可以在单个方法中重用Connection对象吗?

我最初的想法是在继续之前关闭所有资源:

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
    conn = ConnectionFactory.getConnection();
    ps = conn.prepareStatement("SELECT * FROM MYTABLE WHERE COL=?");
    ps.setString(1, "val");
    rs = ps.executeQuery();
    // get values used to determine the next statement type
} catch (SQLException e) {
    LOG.error("SQL failed.", e);
} finally {
    if(rs != null){rs.close();}
    if(ps != null){ps.close();}
    if(conn != null){conn.close();}
}
// Then another SQL statement is needed (either an UPDATE or INSERT).
// Repeat the same pattern to open, use and close the connection

执行以下操作是否同样安全?如果安全的话,真的有好处吗?

//... boilerplate
try {
    conn = ConnectionFactory.getConnection();
    ps = conn.prepareStatement("SELECT * FROM MYTABLE WHERE COL=?");
    ps.setString(1, "val");
    rs = ps.executeQuery();
    // ... more

    ps = conn.prepareStatement("UPDATE MYTABLE SET COL=?")
    // ... etc
} finally {
    if(rs != null){rs.close();}
    if(ps != null){ps.close();}
    if(conn != null){conn.close();}
}

2 个答案:

答案 0 :(得分:1)

应该要做的是使用try-with-resources

//... boilerplate
try (Connection conn = ConnectionFactory.getConnection()) {
    try (PreparedStatement ps = conn.prepareStatement("SELECT * FROM MYTABLE WHERE COL=?")) {
        ps.setString(1, "val");
        try (ResultSet rs = ps.executeQuery()) {
            // ... more
        }
    }

    try (PreparedStatement ps = conn.prepareStatement("UPDATE MYTABLE SET COL=?")) {
        // ... etc
    }
}

答案 1 :(得分:1)

重用连接不是反模式,完全可以。重用连接是两条语句在同一本地JDBC事务中执行的唯一方法。如果您正在编写访问关系数据库的应用程序,则应该了解事务。

实现异常处理的方式容易出错,因为如果在关闭任何资源时引发异常,则以后的资源不会被关闭。如果关闭prepareStatement引发异常,则连接不会关闭。 try-with-resources是一种改进,但是the way try-with-resources handles the edge cases使我避免使用JDBC,而使用嵌套的try-finally块。

如果这里有一个反模式,则它是直接使用JDBC的,它是非常低级的,涉及很多剪切和粘贴操作,并且不便于使用事务或连接池。使用Spring会处理一些细节,例如划分数据库事务,使用连接池以及为您关闭资源。