MySQL - Соединение с использованием шаблона Singleton или ConnectionPool? - PullRequest
1 голос
/ 12 октября 2009

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


Сценарий 1 - шаблон синглтона


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

  static Connection connection;
  private Statement stmt = null;

  connection = createConnection(...)
  stmt = connection.createStatement();

Запросы будут выполняться с использованием:

  stmt.execute();

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


Сценарий 2 - шаблон Singleton с PreparedStatement


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

PreparedStatement pStmt= getConnection().prepareStatement(query);
pStmt.execute();

Используя анализатор кода PMD, я заметил, что pSmt может не закрыться, что действительно так, потому что я не могу закрыть его здесь и не могу дать команду вызывающей стороне закрыть его. Такой подход приводит к следующему сценарию.


Сценарий 3 - шаблон Singleton со статическим PreparedStatement


Все готово, я объявил:

private static PreparedStatement preparedStmt = null;

Мой метод executeQuery () адаптируется к:

setPreparedStmt(getConnection().prepareStatement(query));
getPreparedStmt().execute();

где установщик и получатель просто .. установщики и получатели, с общедоступной видимостью и статическим атрибутом. Этот подход легко понять, и вызывающие абоненты должны будут сами закрывать PreparedStatement (нет проблем, но закрытие PreparedStatement также закроет ResultSet, если это так?). Однако почему-то я чувствую, что повторное использование этого предварительно скомпилированного оператора не так уж и безопасно с транзакционным аспектом базы данных. Здесь есть какие-нибудь опасности?


Сценарий 4 - Использование пула соединений


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

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

4.2 Используя пул соединений, должен ли я использовать Statement или PreparedStatement при получении одного соединения из пула и использовать его для выполнения какого-либо запроса?

4.3 Насколько я понимаю, используя эту стратегию, я должен закрыть соединение после того, как его задача будет выполнена. Но что, если по каким-то причинам соединение не может быть закрыто? Если по какой-то причине это повторится несколько раз, равный размеру пула соединений, мы обречены.

ОК, я остановлюсь здесь, возможно, последуют некоторые обновления, в зависимости от ответов. Мэнни, спасибо.

1 Ответ

1 голос
/ 12 октября 2009

Почти во всех мыслимых случаях я бы использовал пул соединений. Об аспектах обслуживания, производительности и реализации позаботились о вас. Большинство серверов предоставляют вам встроенный источник данных, к которому можно получить доступ через JNDI, а также есть отдельные пулы соединений.

Что касается безопасности, используйте подготовленные операторы для любого запроса, который требует ввода данных пользователем для параметра. Таким образом, пользовательский ввод никогда не сможет разрешить атаку SQL-инъекцией.

А по поводу ваших вопросов:

4.1 : в идеале для каждого запроса страницы будет использоваться 1 соединение. Поэтому, чтобы выяснить, сколько всего подключенных соединений вам нужно, вам нужно посчитать, сколько запросов вы получите за среднее время запроса (скажем, запросов в секунду). Если это число не велико, то будет достаточно количества соединений по умолчанию, предоставляемого большинством пулов соединений (обычно 20, как я видел).

4.2 : Вы можете использовать Statement или PreparedStatement из Соединения, которое вы получаете из пула. В большинстве случаев (включая те, в которых пользовательский ввод используется в запросе) следует использовать PreparedStatements.

4.3 : если вы помещаете код закрытия соединения в блок finally, в котором находится оператор try, и не забываете делать это каждый раз, когда получаете доступ к базе данных, то никогда не сталкивайтесь с проблемой исчерпания соединения.

...