有关正确关闭/提交数据库事务和执行查询的问题

Cat*_*ish 4 java coding-style

我正在努力更新项目,我只想知道这两个问题的最佳实践:

  1. 我应该继续使用Connections/Statements/ResultSet来执行查询还是应该使用其他东西?
  2. 这是提交/关闭Connections/Statements/ResultsSets的正确方法吗?我的意思是我在正确的顺序中使用try/catch/finally块在正确的位置进行提交/关闭?

请提供这些代码段的修改代码示例,以明确您的观点.

select类型方法的代码片段:

public  ArrayList getMethod() {

    ArrayList a = new ArrayList();

    Connection con = null;
    ResultSet rs = null;
    Statement stmt = null;

    try {

        con = BoneCPConnection.getConnectionPool().getConnection();     // get a connection
        con.setAutoCommit(true);            
        stmt = con.createStatement();

        String query = "select * from example";

        rs = stmt.executeQuery(query);

        while(rs.next()) {
            System.out.println("Result: "+ rs.getInt(1));
        }

    } catch (Exception e) {
        System.out.println("Issue with getMethod");
        e.printStackTrace();
    } finally {

        try {
            rs.close();
            stmt.close();
            con.close();
        } catch (Exception e) {
            con = null;
        }

        rs = null;
        stmt = null;
        con = null;
    }

    return a;
}
Run Code Online (Sandbox Code Playgroud)

update类型方法的代码片段

public void updateMethod() {

    ArrayList a = new ArrayList();

    Connection con = null;
    Statement stmt = null;
    int updateCount = null;

    try {

        con = BoneCPConnection.getConnectionPool().getConnection();     // get a connection     
        stmt = con.createStatement();

        String query = "update example set id = 1";

        updateCount = stmt.executeUpdate(query);

        System.out.println("Result: "+ updateCount);    

    } catch (Exception e) {
        System.out.println("Issue with updateMethod");
        e.printStackTrace();
    } finally {

        try {
            con.commit();
            stmt.close();
            con.close();
        } catch (Exception e) {
            con = null;
        }

        stmt = null;
        con = null;
    }
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 7

至少,您应该切换到PreparedStatement普通语句而不是简单语句.这样做的原因是,在大多数情况下,JDBC驱动程序会在创建时将语句发送到数据库,因此可以对其进行预编译.然后,您可以将参数绑定到语句并执行.除了预编译的性能优势之外,您还可以获得一些针对SQL注入攻击的保护,因为您设置参数的方式更强类型化.对Oracle网站上的准备好的陈述有很好的描述.

如果您正在使用Spring(或想要将其添加到系统中),您可以查看JdbcTemplateJdbcDaoSupport类(这里都概述).它的主要优点是它可以为您处理连接清理代码(因此您不必担心错过close呼叫).

同样,如果将Spring添加到项目中,则可以使用它来配置事务(通过注释或使用Spring上下文文件).这将允许您将事务管理从实际实现中拉出来,并使您的Dao中的代码更清晰.

至于你对commit/close的处理:你应该将你的commit语句移出finally块并进入主执行路径.你应该在finally块中保留你的密切语句,但是因为你想要随后发生它们无论发生什么.

使用PreparedStatements更新代码的示例如下:

public void updateMethod() {
    Connection con = null;
    PreparedStatement stmt = null;
    int updateCount = null;

    try {
        con = BoneCPConnection.getConnectionPool().getConnection();
        stmt = con.prepareStatement("update example set id = ?");        
        stmt.setInt(1,1);
        updateCount = stmt.executeUpdate(query);
        con.commit();
    } catch (Exception e) {
       if(con != null){
        con.rollback();
       }
    } finally {

        try {
          if(stmt != null){
            stmt.close();
          }
          if(con != null){                
            con.close();
          }
        } catch (Exception e) {
            con = null;
        }        
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您使用的是Spring的JdbcDaoSuport,它看起来像:

public class YourDao extends JdbcDaoSupport{

  public void updateMethod(){
    String sql = "update example set id = ?";
    getJdbcTemplate().update(sql, new Object[] { new Integer(1)});           
  }

}
Run Code Online (Sandbox Code Playgroud)