Я создаю базовое Java-приложение для загрузки некоторых файлов в базу данных MySQL.Я могу загрузить файлы и заполнить свои таблицы без каких-либо проблем.Однако после разговора с кем-то, кто просмотрел мой код, я, видимо, неправильно закрывал свои соединения и трачу ресурсы.Где я не закрываю связи?Я сделал это неправильно?
Я использую конструкцию try-with-resources в моем классе DbSinger для выполнения подготовленных операторов в моей базе данных, которая должна автоматически закрывать соединение, если реализован интерфейс AutoCloseable, которыйэто в родительском классе Db .Однако метод close () никогда не достигается. DbSinger создается внутри моего main () , а затем запускает его единственный метод populateSingers () с ArrayList из Singer объектов.
Класс соединения
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();
}
}
}
Мой код может выполняться, работает нормально и выполняет то, что ему нужно, но я хочу понять, почему и где я не закрываю соединения, и понять,как я могу решить это.Или, по крайней мере, понять, если я подхожу к этому неправильно.