Безопасно ли использовать статический экземпляр java.sql.Connection в многопоточной системе?
29315 просмотра
2 ответа
Я запускаю веб-приложение на Tomcat. У меня есть класс, который обрабатывает все запросы БД. Этот класс содержит Connection
объект и методы, которые возвращают результаты запроса.
Это объект подключения:
private static Connection conn = null;
У него только один экземпляр (синглтон).
Кроме того, у меня есть методы, которые выполняют запросы, такие как поиск пользователя в БД:
public static ResultSet searchUser(String user, String pass) throws SQLException
Этот метод использует статический Connection
объект. Мой вопрос заключается в том, Connection
безопасно ли использование в статическом потоке объектов? Или это может вызвать проблемы, когда многие пользователи будут вызывать searchUser
метод?
Ответы (2)
77 плюса
мое использование в статическом потоке объекта Connection безопасно?
Точно нет!
Таким образом, соединение будет общим для всех запросов, отправленных всеми пользователями, и, таким образом, все запросы будут мешать друг другу. Но потокобезопасность - не единственная ваша проблема, утечка ресурсов - это и другая ваша проблема. Вы сохраняете одно соединение открытым в течение всего срока службы приложения. Средняя база данных восстанавливает соединение всякий раз, когда оно было открыто слишком долго, что обычно составляет от 30 минут до 8 часов, в зависимости от конфигурации базы данных. Поэтому, если ваше веб-приложение работает дольше, соединение теряется, и вы больше не сможете выполнять запросы.
Эта проблема также применима, когда эти ресурсы хранятся как static
переменные не экземпляра экземпляра класса, который используется многократно.
Вы всегда должны получать и закрывать соединение, оператор и набор результатов в кратчайшей возможной области , предпочтительно внутри того же 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
здесь. Вы должны немедленно прочитать его и сопоставить его с не-JDBC классом, а затем вернуть его, чтобы ResultSet
можно было безопасно закрыть его.
Если вы еще не используете Java 7, используйте try-finally
блок, в котором вы вручную закрываете закрываемые ресурсы в обратном порядке по мере их приобретения. Вы можете найти пример здесь: как часто должны быть закрыты Connection, Statement и ResultSet в JDBC?
Если вы беспокоитесь о производительности соединения, то вместо этого вам следует использовать пул соединений. Это встроено во многие серверы приложений Java EE и даже в базовые контейнеры сервлетов, такие как Tomcat. Просто создайте источник данных JNDI на самом сервере и позвольте вашему веб-приложению захватить его как DataSource
. Это прозрачно уже пул соединений. Вы можете найти пример в первой ссылке списка ниже.
Смотрите также:
- Как подключиться к базе данных / источнику данных JDBC в приложении на основе сервлета?
- Когда мое приложение теряет соединение, как мне его восстановить?
- Использую ли я пул соединений JDBC?
- Показать JDBC ResultSet в HTML на странице JSP с использованием шаблона MVC и DAO
- Руководство по DAO с JDBC
1 плюс
Если вы выполняете только Select
запросы ( searchUser
звучит как только выбор данных), проблем не будет, кроме конфликта потоков.
Насколько я знаю, a Connection
может обрабатывать только один запрос за раз, поэтому, используя один экземпляр, вы по существу сериализуете доступ к базе данных. Но это не обязательно означает, что такой доступ к базе данных всегда безопасен в многопоточной среде. Могут все еще быть проблемы, если одновременный доступ чередуется.
Вопросы из категории :
- java В чем разница между int и Integer в Java и C #?
- java Как я могу определить IP моего маршрутизатора / шлюза в Java?
- java Каков наилучший способ проверки XML-файла по сравнению с XSD-файлом?
- java Как округлить результат целочисленного деления?
- multithreading Что такое состояние гонки?
- multithreading Что такое тупик?
- multithreading Что такое мьютекс?
- multithreading Как начать потоки в plain C?
- servlets Сервлет для обслуживания статического контента
- servlets Конструктор сервлетов и метод init ()
- servlets Различия между куки и сессиями?
- servlets Ошибка в скорости и log4J
- jdbc Как избежать хранения паролей в открытом виде для tomcat server.xml Определение ресурса DataSource?
- jdbc Могу ли я подключиться к SQL Server с помощью аутентификации Windows из веб-приложения Java EE?
- jdbc Как я могу получить размер java.sql.ResultSet?
- jdbc Как выполнить модульное тестирование кода JDBC в Java?
- connection java.net.SocketException: сброс соединения
- connection Как определить общее количество открытых / активных соединений в MS SQL Server 2005
- connection Мгновенно обнаруживать отключение клиента от серверного сокета
- connection Как определить физическое состояние подключения сетевого кабеля / разъема?