У нас есть система, в которой соединение с базой данных устанавливается один раз с использованием обычного метода и передается через соответствующий класс, который будет использоваться. Есть сомнения, что передача соединения с базой данных в качестве параметра различным классам вызовет проблемы, поэтому я проверяю здесь, чтобы увидеть, является ли это на самом деле жизнеспособным, и есть ли лучшие шаблоны для этого?
Я знаю, что есть некоторые инструменты ORM, чтобы сделать постоянство, но мы не можем вдаваться в подробности, пока ...
Любые отзывы приветствуются, спасибо.
java
database
patterns-and-practices
ipohfly
источник
источник
Ответы:
Да, безопасно обойти соединение. Вы обрабатываете соединение во внешнем управляющем блоке. В этом нет ничего небезопасного.
Что небезопасно, так это написание кода, который не гарантирует своевременное удаление соединения должным образом. Забыть очистить ресурс не имеет отношения к его передаче. Вы могли бы так же легко написать код, который оставляет зависшее соединение, никуда его не пропуская.
В C ++ вы защищены RAII, если вы размещаете в стеке или используете умные указатели. В C # сформулируйте жесткое правило, согласно которому все одноразовые объекты (например, соединения) должны быть объявлены в блоке «using». В Java очистите с помощью логики try-finally. Имейте обзоры кода на весь код уровня данных, чтобы гарантировать это.
Наиболее распространенный вариант использования - это когда у вас есть несколько операций, которые можно комбинировать во многих перестановках. И каждая из этих перестановок должна быть атомарной транзакцией (все успешно или откат). затем вы должны передать транзакцию (и, следовательно, соответствующее соединение) всем методам.
Предположим, у нас есть много действий foobar (), которые можно комбинировать различными способами как атомарные транзакции.
Кстати, вы захотите открыть соединения как можно позже, избавиться от них как можно скорее. Ваши товарищи по команде могут быть правы, если вы рассматриваете соединения как членов объекта, представляете их как ненужное состояние и оставляете соединения открытыми гораздо дольше, чем необходимо. Но акт передачи соединения или транзакции в качестве параметра по своей сути не является ошибочным.
КСТАТИ. В зависимости от того, поддерживает ли ваш язык функции первого класса, вы можете выполнить список действий foobar (). Таким образом, одна функция может обрабатывать все варианты действий. Устранение дублирования внешнего управляющего блока для каждой перестановки.
источник
Похоже, вы после инъекции зависимости . То есть пулное соединение создается один раз и вводится везде, где это необходимо. Конечно, передача соединения через параметр метода является одним из способов внедрения зависимости, но контейнер IoC, такой как Guice, PicoContainer или Spring, является другим (более безопасным) способом сделать это.
Использование DI означает, что вы можете аккуратно обернуть логику вокруг создания, открытия, использования и закрытия соединения - вне вашей основной бизнес-логики.
Spring JDBC и др. Являются другими примерами выполнения такого поведения для вас
источник
Передача данных из базы данных, а не данных может привести к проблемам. Поэтому, когда это целесообразно, не передавайте данные из базы данных, если только вы не можете гарантировать надлежащую гигиену базы данных.
Проблема с передачей данных в базе данных состоит в том, что она может быть небрежной. Я видел более одной ошибки в коде, когда кто-то передавал соединение с базой данных, что кто-то затем захватывает набор результатов и сохраняет его в локальном объекте (набор результатов, все еще подключенный к базе данных), а затем связывает курсор в базы данных в течение значительного времени. В другом случае кто-то передал набор результатов кому-то другому (который затем был спрятан), а затем метод, который передал набор результатов, закрыл его (и инструкцию), что привело к ошибкам, когда другие методы пытались работать с набором результатов, которого больше не было.
Все это происходит из-за несоблюдения базы данных, соединения, оператора, набора результатов и их жизненных циклов.
Чтобы избежать этого, существуют существующие шаблоны и структуры, которые лучше взаимодействуют с базами данных и не имеют необходимости в вещах из баз данных, которые должны выходить из классов, в которых они содержатся. Данные поступают, данные уходят, база данных остается на месте.
источник
Root
от Дао. Но затем вы понимаете, что вы также хотите получить способ,Node
не вытаскивая с собой весьRoot
объект. Как вы заставляетеRoot
ДаоNode
вызывать код Дао (то есть: повторное использование), но убедитесь, чтоNode
Дао закрывает соединение только приNode
прямом вызове Дао, и сохраняет соединение открытым приRoot
вызове Дао?Передача
Connection
экземпляров обычно не является проблемой, хотя в большинстве случаев только реализации DAO должны иметь к ним какое-либо отношение. Теперь, когда ваша проблема связана с тем, что соединения не закрываются после использования, на самом деле это легко исправить:Connection
объект должен быть закрыт на том же уровне, на котором он открыт, то есть тем же способом. Я лично использую следующий шаблон кода:Таким образом я гарантирую, что все соединения всегда закрыты, даже если в блоке выдается исключение. Я на самом деле идти до тех пор, используя тот же самый шаблон для
Statement
иResultSet
экземпляров, и все было гладко до сих пор.Изменить 2018-03-29: как указано пользователем 1156544 в комментариях ниже, начиная с Java 7, следует использовать конструкцию try-with-resources. Используя его, шаблон кода, который я предоставил в своем первоначальном ответе, можно упростить так:
источник
dataSource
а неDataSource
(я исправлю свой ответ относительно этого пункта). Точный тип этого объекта будетjavax.sql.DataSource
. В старом коде я использовал одноэлементное управление всеми доступными источниками данных в моих приложениях. Моим DAO не нужно было знать об этом, так какDataSource
экземпляр предоставляется путем внедрения зависимости.есть компромисс в том, чтобы действовать таким образом, а не использовать синглтон, который вы можете получить по мере необходимости. Я делал вещи обоими способами в прошлом.
В общем, вам нужно подумать о последствиях управления соединениями с базой данных, и это может или не может быть ортогонально использованию запросов к базе данных. Например, если у вас есть одно соединение базы данных для данного экземпляра приложения, и оно закрывается, когда оно не используется, это будет ортогонально. Поместите управление в класс синглтона и не передавайте его. Это позволяет вам управлять подключением к БД по мере необходимости. Например, если вы хотите закрывать соединение при каждом коммите (и повторно открывать при следующем вызове), это проще сделать на одиночном, потому что API для этого может быть централизованным.
С другой стороны, предположим, что вам нужно управлять пулом соединений, где для данного вызова может понадобиться любое произвольное соединение. Это может произойти, например, при распределенных транзакциях между несколькими серверами. В этом случае вам, как правило, гораздо лучше передать объект соединения с БД, чем работать с синглетонами. Я думаю, что это обычно более редкий случай, но нет ничего плохого в том, чтобы делать это, когда вам нужно.
источник