#java #sql #static #connection
Вопрос:
Я в замешательстве относительно использования статического соединения для подключения базы данных. Из того, что я прочитал, статическое соединение использовать не следует. Это мой метод:
private static Connection conn()
{
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = (Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
}
return connection;
}
Затем для получения результатов используется новый метод:
public void getResult(ArrayList test)
{
try
{
Connection conn = conn();
String sql = "select id from test";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next())
{
test.add(rs.getInt("id"));
}
conn.close();
} catch (SQLException ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
}
}
Теперь я не знаю, безопасно ли это. Соединение запускается заново каждый раз, когда вызывается метод (?), и я закрываю его. Конечно, объединение пулов соединений было бы полезно для производительности, но безопасно ли это для потоков?
Комментарии:
1. Технически это потокобезопасно, но подвержено утечке соединения в случае возникновения исключения. В
conn.close()
этом случае он не был бы вызван. Онconn.close()
должен быть в блоке finally или в коде, измененном для использования функции try-with-resources, которая будет вызывать его неявно.2. Означает ли это, что я мог бы использовать его в веб-приложении с finally block, и он все равно был бы потокобезопасным?
3. Извините, теперь я вижу, что вы уже ответили на этот вопрос. Я хочу отметить ваш комментарий как ответ.
4. Я скопировал информацию в ответ и добавил немного больше деталей, чтобы сделать ее достойной ответа. 🙂
Ответ №1:
Технически это потокобезопасно, но подвержено утечке соединения в случае возникновения исключения. В conn.close()
этом случае он не был бы вызван. Он conn.close()
должен быть в блоке finally или в коде, измененном для использования функции try-with-resources, которая будет вызывать его неявно.
Функция try-with-resources (Java 7 ) позволяет объявлять переменные, реализующие Autocloseable
интерфейс в операторе try. Эти переменные затем изящно закрываются в конце try
блока.
try( Connection conn = conn(); )
{
//.... other statements
} catch(SQLException e) {
//.... exception code
}
Ответ №2:
Если вы хотите использовать одно соединение, которое вы можете объявить Connection object as private instance object
и всегда check if it is null
перед созданием нового соединения.
private Connection connection = null;
private static Connection conn()
{
if ( connection == null) {
try {
Class.forName("com.mysql.jdbc.Driver").newInstance();
connection = (Connection)DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | SQLException ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
}
}
return connection;
}
public void getResult(ArrayList test)
{
try
{
Connection conn = conn();
String sql = "select id from test";
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while(rs.next())
{
test.add(rs.getInt("id"));
}
} catch (SQLException ex) {
Logger.getLogger(Database.class.getName()).log(Level.SEVERE, null, ex);
}
finally{
try {
conn.close();
conn = null;
}
catch(Exception e)
{
//Unable to close connection
}
}
}