Безопасно ли использовать статический экземпляр java.sql.Connection в многопоточной системе?

java multithreading servlets jdbc connection

29315 просмотра

2 ответа

Я запускаю веб-приложение на Tomcat. У меня есть класс, который обрабатывает все запросы БД. Этот класс содержит Connectionобъект и методы, которые возвращают результаты запроса.

Это объект подключения:

private static Connection conn = null;

У него только один экземпляр (синглтон).

Кроме того, у меня есть методы, которые выполняют запросы, такие как поиск пользователя в БД:

public static ResultSet searchUser(String user, String pass) throws SQLException

Этот метод использует статический Connectionобъект. Мой вопрос заключается в том, Connectionбезопасно ли использование в статическом потоке объектов? Или это может вызвать проблемы, когда многие пользователи будут вызывать searchUserметод?

Автор: Asher Saban Источник Размещён: 12.11.2019 09:10

Ответы (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. Это прозрачно уже пул соединений. Вы можете найти пример в первой ссылке списка ниже.

Смотрите также:

Автор: BalusC Размещён: 24.02.2012 01:53

1 плюс

Если вы выполняете только Selectзапросы ( searchUserзвучит как только выбор данных), проблем не будет, кроме конфликта потоков.

Насколько я знаю, a Connectionможет обрабатывать только один запрос за раз, поэтому, используя один экземпляр, вы по существу сериализуете доступ к базе данных. Но это не обязательно означает, что такой доступ к базе данных всегда безопасен в многопоточной среде. Могут все еще быть проблемы, если одновременный доступ чередуется.

Автор: TPete Размещён: 24.02.2012 11:55
Вопросы из категории :
32x32