Java потокобезопасные соединения с базой данных - PullRequest
3 голосов
/ 25 февраля 2012

Я пишу сервлет, который обрабатывает каждый запрос, получая доступ и изменяя некоторые таблицы в базе данных.Я хочу, чтобы соединения с базой данных были потокобезопасными.Я не хочу использовать для этого уже существующие библиотеки / фреймворки (весна, спящий режим и т. Д.).

Я знаю, что могу использовать Java ThreadLocal для этого следующим образом:

public class DatabaseRegistry { //assume it's a singleton


private Properties prop = new Properties();
    public static final ThreadLocal<Connection> threadConnection = new ThreadLocal<Connection>();

    private Connection connect() throws SQLException {
        try {
            // This will load the MySQL driver, each DB has its own driver
            Class.forName("com.mysql.jdbc.Driver");
            // Setup the connection with the DB
            Connection connection = DriverManager
                    .getConnection("jdbc:mysql://" + prop.getProperty("hostname") + "/" + prop.getProperty("database") + "?"
                            + "user=" + prop.getProperty("username") + "&password=" + prop.getProperty("password"));
            return connection;
        } catch (SQLException e) {          
            throw e;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } 

        return null;

    }

    public Connection getConnection() throws SQLException {

        if(threadConnection.get() == null) {
            Connection connection = connect();
            threadConnection.set(connection);
            return threadConnection.get();
        } else
            return threadConnection.get();
    } 

    private void freeConnection(Connection connection) throws SQLException {
        connection.close();
        threadConnection.remove();
    }
}

Каждый раз, когда вы вызываете getConnection (), новое соединение добавляется к объекту ThreadLocal и затем удаляется, когдаВы освобождаете соединение.

Это правильный способ сделать это, или сама DatabaseRegistry должна расширить класс ThreadLocal?Или есть еще лучший способ сделать все соединения безопасными для потоков?

Спасибо

Ответы [ 3 ]

2 голосов
/ 25 февраля 2012

Я не думаю, что создание потоковых соединений с базами данных является обычной практикой.Обычно вам нужно либо:

  • Сериализировать доступ к некоторой части вашего сервлета, чтобы не было более одного исполняющего кода сервлета за раз (например, реализующего интерфейс SingleThreadModel).
  • Блокировка определенной таблицы / страницы / строки таблицы, чтобы вы могли работать с определенным кортежем (путем изменения уровня изоляции базы данных).
  • Использование оптимистической блокировки для обнаружения измененных строк в таблице (с использованиемнекоторый ссылочный атрибут таблицы, чтобы проверить, совпадает ли текущая версия с той, что в таблице).

AFAIK, типичное использование ThreadLocal для хранения уникального соединения с базой данных для каждого потока, поэтомучто одно и то же соединение может использоваться в различных методах вашей бизнес-логики без необходимости каждый раз передавать его в качестве параметра.Поскольку реализация общего контейнера сервлета использует поток для полного выполнения HTTP-запроса, то два разных запроса гарантируют использование двух разных соединений с базой данных.

2 голосов
/ 25 февраля 2012

Я знаю, что вы сказали, что не хотите использовать библиотеки для этого, но вам будет намного лучше, если вы это сделаете. Выберите стандартный пул соединений (C3P0, DBCP или что-то в этом роде), и вы будете намного счастливее, чем если бы вы запекали свой собственный. Почему вы не можете использовать библиотеку для этого?

0 голосов
/ 25 февраля 2012

Я не уверен, почему вы хотите, чтобы ваши соединения с БД были поточно-ориентированными.Установление соединения с базой данных в большинстве случаев является самой длинной частью транзакции.Обычно соединения повторно используются между запросами, а пулы открытых соединений управляются (через каркасы или, более типично, серверы приложений).

Если вы беспокоитесь о одновременных изменениях в тех же таблицах, вы можете захотеть взглянуть на синхронизированные методы: http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

...