简体   繁体   English

JDBC连接关闭

[英]JDBC Connection close

can someone tell me where and how I have to close the connection here? 有人可以告诉我在这里以及如何关闭连接吗? Do I have to close the Connection in the Connection class or in the Controller class? 我必须在Connection类或Controller类中关闭Connection吗? I already tried to put followin at the end of the method in the connection class: 我已经尝试将followin放在连接类中方法的末尾:

if (conn != null) {
        try {
            conn.close();
        } catch (SQLException e) { /* ignored */}
    } 

But then I get: "No operations allowed after statement closed." 但是然后我得到:“语句关闭后不允许进行任何操作。”

Here is my Code: 这是我的代码:

public class DB_Connection {

String url = "XXX";

Statement statement;

public DB_Connection (){
       try {

           Connection con =  (Connection) DriverManager.getConnection(url);
           statement = (Statement) con.createStatement();

       }
       catch (SQLException ex){
           System.out.println("Failed connection");
       }
   }

public void addSubject(String subject) throws SQLException {

     try {
     statement.executeUpdate("INSERT INTO `Subject` VALUES ('" + subject + "')" );
     System.out.println("Added " + subject + "to database");
     } catch(SQLException e) {
         System.out.println("SQL Exception");
     }
 }
}

And I call it from here: 我从这里调用它:

public class MenuController {

    @FXML
        public void SendSubject(ActionEvent e) throws IOException, SQLException {
            DB_Connection connection = new DB_Connection();
            connection.addSubject("English");

        }

    }

Thanks for your help! 谢谢你的帮助!

You need to close the connection after you have finished using it. 使用完后,需要关闭连接。 There are many ways to deal with that, but here's what I suggest you do: 有很多方法可以解决这个问题,但是我建议您这样做:

public class DBConnection implements AutoCloseable {
    private String url = ...
    private Connection con;
    private Statement statement;

    public DBConnection () throws SQLException {
        try {
             con = DriverManager.getConnection(url);
             statement = con.createStatement();
        } finally {
             // Avoid leak if an exception was thrown in createStatement
             if (statement == null) {
                 con.close();
             }
        }
    }

    public void addSubject(String subject) throws SQLException {
        statement.executeUpdate("INSERT INTO `Subject` VALUES ('" + 
                                subject + "')" );
    }

    public void close() throws SQLException {
        con.close();
    }
}

Then use it like this: 然后像这样使用它:

try (DBConnection connection = new DBConnection()) {
     connection.addSubject("English");
}

Explanation / commentary: 说明/评论:

  1. The close() method is the way that the application tells the DBConnection class "I have finished". close()方法是应用程序告诉DBConnection类“我已经完成”的方式。
  2. Declaring DBConnection as `AutoCloaseable means that we can use try-with-resources to manage the closure ... which is simpler and more robust. DBConnection声明为“ AutoCloaseable”意味着我们可以使用try-with-resources来管理闭包...这更简单,更可靠。
  3. The instance variables are private as per good OO design principles. 根据良好的OO设计原则,实例变量是private
  4. The class name is corrected per the Java conventions. 根据Java约定更正了类名。
  5. We still needed to be careful to ensure that we don't leak a connection if an exception occurs in the constructor itself. 我们仍然需要小心以确保如果构造函数本身发生异常,我们也不会泄漏连接。
  6. We allow SQLException to propagate to the caller. 我们允许SQLException传播到调用方。 Those exceptions cannot be handled properly in DBConnection class itself. 这些异常不能在DBConnection类本身中正确处理。

The other approach is to do away with the DBConnection class entirely, and have the calling code take care of the connection object and the statements for itself. 另一种方法是完全取消DBConnection类, DBConnection调用代码自行处理连接对象和语句。 Certainly, in this small example the DBConnection abstraction adds minimal value. 当然,在这个小例子中, DBConnection抽象增加了最小值。

When you get it going following Stephen's guidance, take a look at PreparedStatement as well... 当您遵循Stephen的指导进行操作时,请同时查看PreparedStatement ...

Declare PreparedStatement rather than Statement : 声明PreparedStatement而不是Statement

    private PreparedStatement pStmt;

Create the PreparedStatement : 创建PreparedStatement

     pStmt = con.prepareStatement("INSERT INTO `Subject` VALUES (?)");

Reuse the PreparedStatement : 重用PreparedStatement

public void addSubject(String subject) throws SQLException {
    pStmt.setString(1, subject);
    pStmt.executeUpdate();
    pStmt.clearParameters();
}

Allows re-use and some protection from injection. 允许重复使用,并有一定的防注入保护措施。

Don't hold connections etc. as member variables at all. 根本不将连接等作为成员变量保存。 You should make them all ( Connection, Statement/PreparedStatement, ResultSet ) local variables and use the try-with-resources idiom. 您应该使它们全部( Connection, Statement/PreparedStatement, ResultSet )局部变量,并使用try-with-resources惯用语。

Don't close conn object in the Connection class, Better to close in DAO class only or in the Main method or in the Method itself. 不要在Connection类中关闭conn对象,最好只在DAO class或在Main methodthe Method itself.关闭the Method itself.

for example: 例如:

public void addSubject(String subject) throws SQLException {
    ........
    ........//**some operations**
    // close here after some operation done
   if (conn != null) {
    try {
        conn.close();
    } catch (SQLException e) { sysout(e);}
} 
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM