должно ли соединение db быть одноэлементным?

Как лучше всего в Java создать синглтон? Должно ли соединение с БД быть одноэлементным (будучи одноэлементным, оно автоматически потокобезопасно)? Поскольку теоретически БД не может быть доступна для многих пользователей одновременно.


person spauny    schedule 28.06.2011    source источник
comment
Кто вам сказал, что если что-то одноэлементное, оно автоматически потокобезопасно? Кроме того, к БД обычно обращаются одновременно многие пользователи.   -  person Reverend Gonzo    schedule 28.06.2011
comment
@Reverend Gonzo Есть ли синглтон, который не является потокобезопасным?   -  person spauny    schedule 28.06.2011
comment
Синглтон - это просто объект, для которого создается только один экземпляр. Это не имеет отношения к потокобезопасности объекта. Если внутренняя часть этого объекта не является потокобезопасной, превращение его в синглтон не делает его потокобезопасным. Объект Connection не является потокобезопасным, поскольку его нельзя использовать одновременно из нескольких потоков. Сделав его одноэлементным, вы склонны к серьезным проблемам, если попытаетесь получить доступ к этому соединению из нескольких потоков. (Вам следует использовать пул соединений (через библиотеку или ThreadLocal), чтобы иметь одно соединение для каждого потока.   -  person Reverend Gonzo    schedule 28.06.2011


Ответы (4)


Соединение с БД обычно не должно быть синглтоном.

Две причины:

  1. многие драйверы БД не являются потокобезопасными. Использование синглтона означает, что если у вас много потоков, все они будут использовать одно и то же соединение. Шаблон singleton не обеспечивает безопасности потоков. Это просто позволяет многим потокам легко совместно использовать «глобальный» экземпляр.
  2. Лично я считаю, что Синглтон часто приводит к плохому дизайну: см. Этот пост (кто-то другой) http://tech.puredanger.com/2007/07/03/pattern-hate-singleton/

Вместо этого рассмотрите пул базы данных. Пул является общим (и при желании может быть синглтоном). Когда вам нужно работать с базой данных, ваш код делает следующее:

getConnectioFromPool();

doWork()
closeConnection() // releases back to pool

Примеры библиотек пулов:

person Dave    schedule 28.06.2011
comment
Следует ли загружать коннектор БД в ServletContext, если коннектор не Singletone? Будет ли это хороший стиль ООП? - person gkiko; 10.08.2012
comment
Обычно я использую spring для внедрения объединенных источников данных в свои объекты. Объединенный источник данных может поступать из JNDI, если сервер приложений поддерживает его, или путем определения источника данных в Spring. - person Dave; 11.08.2012
comment
Как правило, эти пункты очень верны; однако есть некоторые БД, такие как MongoDB, разработчики которых специально рекомендовали шаблон Singleton, а некоторые БД ДЕЙСТВИТЕЛЬНО гарантируют безопасность потоков. По сути, прочтите спецификации своей БД и рассмотрите приложение ... - person jsh; 07.05.2013
comment
Я не думаю, что это так ужасно использовать синглтон для глобальных ресурсов, когда у вас есть приложение без истинной потоковой передачи, например. приложение python или dart. - person Anthony O; 19.10.2020

Лучшим способом создания синглтона (на сегодняшний день) является шаблон синглтона enum (Java enum singleton)

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

public ConnectionProvider {
  private Connection conn;

  public static Connection getConnection() {
    if (conn == null || conn.isClosed()) {
      conn = magicallyCreateNewConnection();
    }
    return conn;
  }
}

(не потокобезопасный - при необходимости синхронизируйте)

person Andreas Dolk    schedule 28.06.2011
comment
Да, Singleton - не лучший выбор для объекта Connection. Однако следует ли создавать одноэлементный источник данных, поддерживаемый пулом db? - person bluelurker; 16.08.2016

Как лучше всего в Java создать синглтон?

Следуйте инструкциям по созданию шаблонов проектирования. т.е. частный конструктор и т. д.

Должно ли соединение с БД быть одноэлементным (будучи одноэлементным, оно автоматически потокобезопасно)?

Создание соединения с БД как одноэлементного может быть плохим выбором во многих сценариях. Используйте его только в том случае, если уверены, что параллелизм БД вам не нужен. Если у вас есть несколько пользователей, вошедших в систему одновременно, или даже если ваш единственный пользователь порождает множество потоков, которым необходим доступ к БД, то пул подключений к БД - лучший выбор. Вы можете использовать пулы соединений apache или tomcat db. Эти классы определены, например, в пакете

org.apache.commons.dbcp.*;

org.apache.tomcat.dbcp.dbcp.*;

где dbcp означает пул соединений с базой данных.

Самая большая причина использования пула соединений заключается в том, что в среднем время, необходимое для доступа к БД (DML и т. Д.), Намного меньше, чем время, необходимое для создания соединения, а затем его закрытия. Кроме того, не забудьте закрыть переменные ResultSet, PreparedStatement и Connection после завершения транзакции.

Поскольку теоретически БД не может быть доступна для многих пользователей одновременно.

Почему нет? БД в большинстве случаев предполагается использовать одновременно. У вас есть эти уровни изоляции БД - READ_COMMITTED, READ_UNCOMMITTED, SERIALIZED и т. Д. SERIALIZED - это случай, когда ваша БД становится доступной для одного пользователя.

person Basanth Roy    schedule 28.06.2011

Синглтоны - это шаблон - нет явного способа создать его, вы просто следуете практике проектирования.

Итак, если вы используете базу данных, которая может обрабатывать одновременные операции чтения / записи (например, MySQL), вам не нужно так сильно беспокоиться о безопасности потоков. Если вы используете БД, которая плохо выполняет параллельную запись (SQLite), то теоретически должен работать синглтон.

person jefflunt    schedule 28.06.2011