Ответ 1
мое использование в статическом потоке объекта Connection безопасно?
Точно нет!
Таким образом, соединение будет общим для всех запросов, отправленных всеми пользователями, и, таким образом, все запросы будут мешать друг другу. Но потокобезопасность - не единственная ваша проблема, утечка ресурсов - это и другая ваша проблема. Вы сохраняете одно соединение открытым в течение всего срока службы приложения. Средняя база данных будет восстанавливать соединение всякий раз, когда оно было открыто слишком долго, что обычно составляет от 30 минут до 8 часов, в зависимости от конфигурации БД. Поэтому, если ваше веб-приложение будет работать дольше, соединение будет потеряно, и вы больше не сможете выполнять запросы.
Эта проблема также применима, когда эти ресурсы хранятся в виде static
переменной экземпляра non- экземпляра класса, который используется многократно.
Вы всегда должны получать и закрывать соединение, оператор и набор результатов в кратчайшей возможной области, предпочтительно внутри того же блока try-with-resources
в котором вы выполняете запрос в соответствии со следующей идиомой JDBC:
public User find(String username, String password) throws SQLException {
User user = null;
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT id, username, email FROM user WHERE username=? AND password=md5(?)");
) {
statement.setString(1, username);
statement.setString(2, password);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
user = new User();
user.setId(resultSet.getLong("id"));
user.setUsername(resultSet.getString("username"));
user.setEmail(resultSet.getString("email"));
}
}
}
return user;
}
Обратите внимание, что вы не должны возвращать ResultSet
здесь. Вы должны немедленно прочитать его и сопоставить его с классом non- JDBC, а затем вернуть его, чтобы ResultSet
можно было безопасно закрыть.
Если вы еще не работаете в Java 7, используйте блок try-finally
котором вы вручную закрываете закрываемые ресурсы в обратном порядке по мере их приобретения. Вы можете найти пример здесь: как часто должны быть закрыты Connection, Statement и ResultSet в JDBC?
Если вы беспокоитесь о производительности подключения, то вам следует использовать вместо этого пул подключений. Это встроено во многие серверы приложений Java EE и даже в базовые контейнеры сервлетов, такие как Tomcat. Просто создайте источник данных JNDI на самом сервере и позвольте вашему веб-приложению захватить его как DataSource
. Это прозрачно уже пул соединений. Вы можете найти пример в первой ссылке списка ниже.