[英]SQL connections dangling: Where am I not correctly closing up connections correctly?
我正在構建一個基本的Java應用程序,以將一些文件加載到mysql數據庫中。 我能夠加載文件並填充表格而不會出現任何問題。 但是,在與檢查了我的代碼的人交談之后,我顯然沒有正確關閉我的連接並浪費了資源。 我在哪里不關閉連接? 我做錯了嗎?
我在DbSinger類中使用try-with-resources構造執行對數據庫的准備好的語句,只要實現了AutoCloseable接口(位於Db的父類中),該數據庫就應自動關閉連接。 但是,永遠不會達到close()方法。 DbSinger在我的main()中實例化,然后使用Singer對象的ArrayList運行它的單個方法populateSingers() 。
連接等級
public class SQLConnection {
private static final String servername = "localhost";
private static final int port = 3306;
private static final String user = "ng_user";
private static final String pass = "ng";
private static final String db = "ng_music";
private static final String connectionString = "jdbc:mysql://" + servername + ":" + port + "/" + db;
public Connection provide() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(connectionString, user, pass);
}
catch (SQLException | ClassNotFoundException e) {
throw new SQLConnectionException(e);
}
}
public class SQLConnectionException extends RuntimeException {
SQLConnectionException(Exception e) {super(e);}
}
}
抽象父類
public abstract class Db implements AutoCloseable{
private Connection connection;
Db() {
SQLConnection sqlC = new SQLConnection();
this.connection = sqlC.provide();
}
@Override
public synchronized void close() throws SQLException {
if(connection != null) {
connection.close();
connection = null;
System.out.println("Connection closed");
}
}
Connection getConnection() {
return connection;
}
boolean checkIfPopulated(String query){
try {
PreparedStatement ps = getConnection().prepareStatement(query);
ResultSet rs = ps.executeQuery();
return !rs.next();
} catch (SQLException e) {
e.printStackTrace();
}
return true;
}
}
具體類對歌手表執行對數據庫的查詢
public class DbSinger extends Db {
public DbSinger() {
super();
}
public void populateSingers(ArrayList<Singer> singers) {
String populateSingersQuery = "insert into ng_singers(name, dob, sex) values(?,?,?)";
if(!checkIfPopulated("select * from ng_singers")){
System.out.println("Singer Table is already populated");
return;
}
try (PreparedStatement ps = getConnection().prepareStatement(populateSingersQuery)) {
for (Singer s : singers) {
ps.setString(1, s.getName());
ps.setDate(2, java.sql.Date.valueOf(s.getDob()));
ps.setString(3, s.getSex());
ps.addBatch();
}
ps.executeBatch();
System.out.println("Singers added to table");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
我的代碼能夠執行,能夠正常運行並完成所需的工作,但是我想了解為什么不關閉連接的原因和位置,以及如何解決此問題。 或者至少了解我是否正在解決這個錯誤。
您的代碼是舊的方式。 而且您確實需要手動關閉。 但是,對於Java 8,您可以try with resource
以下try with resource
使用try with resource
,
try (Connection conn = ds.getConnection();
Statement stmt = conn.createStatement()) {
try {
stmt.execute(dropsql);
} catch (Exception ignore) {} // ignore if table not dropped
stmt.execute(createsql);
stmt.execute(insertsql);
try (ResultSet rs = stmt.executeQuery(selectsql)) {
rs.next();
} catch (Exception e2) {
e2.printStackTrace();
return("failed");
}
} catch(Exception e) {
e.printStackTrace();
return("failed");
}
對於您的情況,您需要在try-with-resources
語句中實例化DBSinger類以關閉基礎連接。
而不是做:
DbSinger dbSinger = new DbSinger();
您需要做:
try (DbSinger dbSinger = new DbSinger()) {
// Your other code
}
這樣,將自動調用您在Db
類中覆蓋的close()
方法。
另外, preparedStatement
checkIfPopulated
方法關閉在checkIfPopulated
方法中創建的checkIfPopulated
:
try (PreparedStatement ps = getConnection().prepareStatement(query)) {
// Other codes
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.