Безопасно ли использовать статический экземпляр java.sql.Connection в многопоточной системе? - PullRequest
48 голосов
/ 24 февраля 2012

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

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

private static Connection conn = null;

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

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

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

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

Ответы [ 2 ]

76 голосов
/ 24 февраля 2012

мое использование в статическом потоке объекта 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, тогда используйте *Блок 1030 *, в котором вы вручную закрываете закрываемые ресурсы в обратном порядке по мере их приобретения.Вы можете найти пример здесь: Как часто должны быть закрыты Connection, Statement и ResultSet в JDBC?

Если вы беспокоитесь о производительности соединения, тогда вам следует использовать пул соединений.Это встроено во многие серверы приложений Java EE и даже в базовые контейнеры сервлетов, такие как Tomcat.Просто создайте источник данных JNDI на самом сервере и позвольте вашему веб-приложению захватить его как DataSource.Это прозрачно уже пул соединений.Вы можете найти пример в первой ссылке списка ниже.

См. Также:

1 голос
/ 24 февраля 2012

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

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

...