Здравствуйте, John_Headlong, Вы писали:
J_H>Здравствуйте, C0s, Вы писали:
C0s>>в сравнении с типичными механизмами, предоставляемыми СУБД, этот — медленнее, потому что подменяет их с помощью довольно ресурсоемких технологий C0s>>насколько медленнее сложно оценить, но для упомянутого мной примера с записями информации об обработанных сообщениях, поступающих с высокой плотностью, можно, например, такие моменты выделить: C0s>>- обработчики будут кластеризованы, чтобы выдержать высокий поток, а вышеупомянутый генератор с кэшем либо будет некластеризуемым и станет узким местом, либо потребует усовершенствования и станет головной болью при деплойменте приложения, чтобы развести разные экземпляры генератора по диапазонам значений
J_H>А СУБД здесь почему не станет узким местом???
да не должно — разработчики СУБД тоже и кэши наворачивают, и вообще для нормальной oltp СУБД первичные ключи — краеугольный камень, и реализациям операций для них уделяется повышенное внимание — просто потому, что большинство задач для такой субд — вставки и выборки по первичному/уникальному ключу
J_H>Кроме того, вспомним о том, что изначально этот механизм предназначен для использования как не просто генератор неких ключей, а как генератор ключей для CMP Entity Beans. То есть предполагается ИЗНАЧАЛЬНО, что приложение использует ресурсоемкие технологии в виде CMP Entity Beans. Приложения, о которых говорите вы, — это, согласитесь, спецслучай, заслуживающий спецсредств для реализации. Платформа J2EE, насколько понимаю я, никогда не позиционировалась как платформа для приложений реального времени.
звучит как "мы вот здесь выбрали ресурсоемкое решение задачи, поэтому совершенно оправданно сопутствующие ей дополнительные задачи также решить ресурсоемко"
кстати, я не говорил о реальном времени — откуда это? я всего лишь привел пример задачи, которая по требованиям (плотность потока=x) решается кластеризацией с вычисленным количеством узлов n(x). если генератор значений придется доводить до кластеризуемого состояния (а у Маринеску, насколько я помню, он не кластеризуемый), то невелика цена этому генератору.
при этом я хочу заметить, что я просто выбрал некий граничный вид задачи, чтобы лучше показать слабости и без того непростого подхода, как custom-решение уже решенной задачи.
C0s>>- даже с кэшем все равно генерация происходит в своей транзакции (requires new). думаю, не все аппсерверы смогут обеспечить оптимальное начало/конец глобальной транзакции даже в случае с отсутствием взаимодействия с БД, а если смогут — то потребуются усилия при деплойменте по настройке использования менеджера транзакции
J_H>Об оптимизации распределенных транзакций, ограниченных одним источником данных, сказано в спецификации XA, глава 2 Model and Definitions, пункт 2.3 Transaction Completetion and Recovery, подпункт 2.3.2 Protocol Optimisations на странице 8:
J_H>· Read-only J_H>· One-phase Commit
цитировть-то и я умею, но предлагаю порассуждать — распределенное приложение, как следствие, используемый менеджер глобальных транзакций — отдельный процесс. для начала и конца транзакции уже, как минимум, получаем межпроцессное взаимодействие, а то и сетевое, причем требующее дополнительного коннекта. хотя всего-то хотелось получить уникальное значение.
J_H>Спецификация выпущена в декабре 1991 года. Думаю, эти соображения изначально учитываются разработчиками контейнеров, которые более глубоко понимают накладные расходы, связанные с глобальными транзакциями, чем мы с вами.
C0s>>я имел в виду не всю книгу, в которой хватает нормальных мыслей, а только конкретный паттерн. не забывайте, что книга старая, а производители аппсерверов не сидят сложа руки
J_H>Можете что-то более новое посоветовать, где затронут этот вопрос?
документации аппсерверов, очевидно. я надеюсь, цель общения на форуме, все-таки, не в переброске цитатами и метриками, а способ найти подход к какой-то конкретной задаче?
как мне кажется, после прочтения основный спецификаций, уже опыт должен превалировать над чтением
C0s>>гарантия именно в том, что типовых способов на стороне СУБД — 2: sequences или автогенерация (инкремент или применение триггера on insert) C0s>>с точки зрения appserverа это: C0s>>- либо запрос значения ключа перед вставкой (например, выполнение select, возвращающего следующее значение sequence) C0s>>- либо запрос у СУБД получившегося в ней значения после вставки C0s>>и то и другое — не более, чем настройки, которые достаточно вынести в ejb-дескриптор C0s>>т.е. задача не такая уж большая, и производители аппсерверов беспокоятся о ее решении
J_H>Вы только что рассуждали о произволительности, а вот здесь получается, что на каждую вставку необходимо два обращения в БД: одно для извлечения очередного значения ключа, второе на собственно вставку. Именно эти вопросы рассматриваются в книге, именно поэтому, например, в предложенном там решении используется сессионный фасад для Entity-компонента, предоставляющего доступ к таблице, где хранятся очередные значения ключей всех сущностей. Этот сессионный фасад огранизует кеширование блоков кодового пространства, сводя всю операцию (в ПОДАВЛЯЮЩЕМ БОЛЬШИНСТВЕ случаев) к простому инкременту счетчика в памяти.
главное не количество обращений (в рамках нормальной транзакции серьезного приложения обращений все равно больше 10), а то, что они производятся в рамках одного коннекта.
в случае с использованием ejb-генератора значений, как я уже пытался показать, будет либо лишний коннект к отдельному менеджеру транзакций, либо дополнительные трудности с настройкой использования локального менеджера транзакции для этого генератора (если аппсервер такое предоставит), превышающие затраты на освоение зависимых от поставщика этого аппсервера настроек для генерации уникальных ключей средствами СУБД
C0s>>вообще, в серьезном приложении обычно приходится использовать jms, т.к. это и удачный инструмент для событийного по своей сути программирования, балансирует нагрузку, средство интеграции и т.п. .... естественно в связке с СУБД
J_H>При чем тут JMS??? Мы рассуждаем о генерации первичных ключей для CMP Entity Beans.
все-таки 'cmp entity beans' — подсознательно я полагаю, что это признак серьезного приложения. т.е. приложение строится с использованием ejb. так и быть, оставим jms в стороне, но напомню, что есть mdb — такой вид ejb. и наверняка его тоже придется использовать. и тогда список подходящих СУБД все равно будет сокращен.
можно, конечно, и проще сказать — заказчик серьезного приложения обычно будет заботиться, чтобы использовалась приличная СУБД...
J_H>>>Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.
в моем опыте и опыте других посетителей этого форума — это, прежде всего, большие возможности. например, когда возникает необходимость эффективной выборки части данных из нескольких таблиц, cmp курит в сторонке, а hibernate щелкает как орешки
т.е. можно сказать, что все идет от задач. мои задачи с помощью hibernate я решаю так, как мне нравится. когда я аналогичные задачи пытался решать с помощью cmp ejb, то либо они не поддавались нормальному решению, либо решались так, как меня не устраивало (лишние селекты вместо joinа, отсутствие возможности внятно ограничить список выбираемых полей и т.п.).
C0s>>это уже в поиск — на этом форуме есть отдельные нитки обсуждений hibernate vs entity ejb vs jdo и т.п. C0s>>в контексте данного вопроса упомяну лишь, что hibernate удачнее, чем паттерн Флойда Маринеску, генерирует primary key values, потому что: C0s>>- использует возможности базы напрямую без лишних слоев C0s>>- знает массу диалектов баз, и пользователю hibernate не приходится сильно напрягаться
J_H>А у Флойда Маринеску не надо ничего знать ни о каких диалектах, а реализовав шаблон один раз, можно использовать его везде, ничего не настраивая. Так что запарок тоже не особо много, согласны?
мне с hibernate тоже не надо знать о деталях диалектов, достаточно помнить об их существовании
C0s>>- аппсервер-независим
J_H>Что здесь имеется в виду? Entity Beans прекрасно стандартизованы и поддерживаются всеми уважающими себя серверами приложений. Объем специфических для контейнера настроек не велик, он касается, прежде всего, отображения на структуру источника данных (для чего есть инструментарий) и настройки специфических параметров, влияющих на производительность, например размера пулов и таймаутов. Эти настройки на уровне EJB было глупо стандартизовывать, поскольку эта технология изначально оринетирована на поддержку источников данных самой различной природы — это производители только реляционные СУБД поддерживают, а на уровне платформы заложены более широкие возможности.
в реальном приложении приходится использовать много сторонних библиотек (commons-*, например), одной больше — другой меньше, на сложность деплоймента это не влияет. я имею в виду, что если задеплоить на новый аппсервер приложение, использующее hibernate, будет проблемой, то эта проблема — рук и/или аппсервера. для нормальных аппсерверов проблемы быть не должно
кстати, насчет "Entity Beans прекрасно стандартизованы и поддерживаются всеми уважающими себя серверами приложений": ejb в полном объеме (т.е. с entity beans) приходится поддерживать, прежде всего, для шильдика "J2EE1.3-fully compatible аппсервер". так уж стандарт определили, и маркетинговые соображения производителей серверов подстегивают.
но для конкретного приложения маркетинговые соображения будут другими — важно не с помощью чего написано приложение, а как оно работает — быстро или нет, легко ли его расширить, удовлетворив очередной позыв заказчика, или нет.
Re[4]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, John_Headlong, Вы писали:
J_H>А мне казалось, что книга под названием EJB Design Patterns предлагает решения распространенных практических проблем для использования как раз именно в серьезных приложениях. А что бы вы посоветовали почитать на затронутую тему?
Все что связано с Design Patterns косательно конкретной технологии это не про то как надо строить архитекуру, а про то как обходить проблеммы возникающие при реализации архитекруты используя данную конкретную технологию. Особенно это касается EJB.
J_H>Это понятно, но где гарантия, что при переносе решения с одного сервера приложений на другой сервер приложений или при подмене одной СУБД другой СУБД не возникнет проблем? Средства генерации первичных ключей и все тонкости, что с ними связаны, практически не стандартизованы, здесь каждый производитель СУБД считает своим долгом отличиться, проявив тем самым свою "уникальность" на рынке. В случае возникновения таких проблем это уже затронет и разработчиков, а не только deployer'а. Приятность же кроссплатформенного решения как раз и состоит в том, что это гарантированный результат в любой конфигурации, разве нет? Причем эта кроссплатформенность как на уровне серверов приложений, так и на уровне СУБД. Причем последняя может вовсе не поддерживать никаких средств генерации уникальных ключей.
Кроссплатформенность на уровне серверов приложений (и уж тем более на уровне СУБД) — утопия. В большестве случаев такая кроссплатформенность не требуется. Большинство EE систем пишутся под заказ, где заказчик выложил круглую сумму денег за преобретенные АПП И БД сервера и выкладывать еще ему нету необходимости.
Если пишется коробочный продукт и требуется кроссплатформенность, то достигается это все выделением непереносимого кода в отдельные интерфейсы и реализацей их для каждой требуемой платформы.
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[4]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, John_Headlong, Вы писали:
J_H>Ну почему же этот способ неэффективен? Как раз в решении, описанном в книге, очень много внимания уделяется именно эффективности реализации механизма. Там ведь не тупой инкремент счетчика, который хранится в БД, а организовано кеширование диапазонов значений ключей, чтобы в подавляющем числе случаев генерация ключа сводилась к инкременту числа в памяти. Автор позаботился даже о тонкой расстановке транзакционных атрибутов, чтобы при массированном использовании механизма это не приводило к длительной блокировке конкурирующих транзакций. Поясните, пожалуйста, в чем вы видите неэффективность?
в сравнении с типичными механизмами, предоставляемыми СУБД, этот — медленнее, потому что подменяет их с помощью довольно ресурсоемких технологий
насколько медленнее сложно оценить, но для упомянутого мной примера с записями информации об обработанных сообщениях, поступающих с высокой плотностью, можно, например, такие моменты выделить:
— обработчики будут кластеризованы, чтобы выдержать высокий поток, а вышеупомянутый генератор с кэшем либо будет некластеризуемым и станет узким местом, либо потребует усовершенствования и станет головной болью при деплойменте приложения, чтобы развести разные экземпляры генератора по диапазонам значений
— даже с кэшем все равно генерация происходит в своей транзакции (requires new). думаю, не все аппсерверы смогут обеспечить оптимальное начало/конец глобальной транзакции даже в случае с отсутствием взаимодействия с БД, а если смогут — то потребуются усилия при деплойменте по настройке использования менеджера транзакции
т.е. либо это просто работать будет медленнее, либо потребуются усилия при разработке и/или деплойменте, которые перекроют усилия, необходимые для изучения возможностей потенциально применимых аппсерверов.
C0s>>сам пример в указанной, imho, больше содержит учебной информации для размышления, нежели применим на практике в серьезных приложениях
J_H>А мне казалось, что книга под названием EJB Design Patterns предлагает решения распространенных практических проблем для использования как раз именно в серьезных приложениях. А что бы вы посоветовали почитать на затронутую тему?
я имел в виду не всю книгу, в которой хватает нормальных мыслей, а только конкретный паттерн. не забывайте, что книга старая, а производители аппсерверов не сидят сложа руки
C0s>>большинство СУБД имеет либо sequences, либо auto-increment. также в некоторых (для меня — экхотических) случаях применяются триггеры C0s>>зная об этом, ведущие производители контейнеров эти случаи уже так или иначе закрыли, для применения достаточно разбираться в конкретных форматах вендор-зависимых частей ejb-дескрипторов C0s>>так или иначе, а разработчики программы страдают меньше всех — потому что дескриптор настраивает DEPLOYER
J_H>Это понятно, но где гарантия, что при переносе решения с одного сервера приложений на другой сервер приложений или при подмене одной СУБД другой СУБД не возникнет проблем? Средства генерации первичных ключей и все тонкости, что с ними связаны, практически не стандартизованы, здесь каждый производитель СУБД считает своим долгом отличиться, проявив тем самым свою "уникальность" на рынке. В случае возникновения таких проблем это уже затронет и разработчиков, а не только deployer'а.
гарантия именно в том, что типовых способов на стороне СУБД — 2: sequences или автогенерация (инкремент или применение триггера on insert)
с точки зрения appserverа это:
— либо запрос значения ключа перед вставкой (например, выполнение select, возвращающего следующее значение sequence)
— либо запрос у СУБД получившегося в ней значения после вставки
и то и другое — не более, чем настройки, которые достаточно вынести в ejb-дескриптор
т.е. задача не такая уж большая, и производители аппсерверов беспокоятся о ее решении
J_H>Приятность же кроссплатформенного решения как раз и состоит в том, что это гарантированный результат в любой конфигурации, разве нет? Причем эта кроссплатформенность как на уровне серверов приложений, так и на уровне СУБД. Причем последняя может вовсе не поддерживать никаких средств генерации уникальных ключей.
я думаю, что СУБД, которая не поддерживает ничего для генерации уникальных ключей, вряд ли будет применима с аппсервером. потому, что в ней, думаю, еще и транзакций не будет и много еще чего.
вообще, в серьезном приложении обычно приходится использовать jms, т.к. это и удачный инструмент для событийного по своей сути программирования, балансирует нагрузку, средство интеграции и т.п. .... естественно в связке с СУБД
как следствие имеем распределенные глобальные транзакции, в которых участники должны поддерживать XA-протокол. в качестве домашнего задания могу предложить найти список СУБД, поддерживающих XA/2PC, и понять, так ли уж сильно друг от друга они отличаются в способах генерации primary key values.
C0s>>но мне больше нравится подход hibernate — мы его используем вместо entity ejb. там есть несколько разных генераторов первичных ключей, в т.ч. поддержка sequences, auto-inc, а также поддержка автовыбора одного из этих 2х наиболее популярных способов в зависимости от используемой СУБД. C0s>>настройки же делаются исключительно в xml hibernate-мэппингов без нагрузки на исходный текст программы
J_H>Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.
это уже в поиск — на этом форуме есть отдельные нитки обсуждений hibernate vs entity ejb vs jdo и т.п.
в контексте данного вопроса упомяну лишь, что hibernate удачнее, чем паттерн Флойда Маринеску, генерирует primary key values, потому что:
— использует возможности базы напрямую без лишних слоев
— знает массу диалектов баз, и пользователю hibernate не приходится сильно напрягаться
— аппсервер-независим
Re: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, secam, Вы писали:
S>Приветствую !
S>Есть такой вопрос... Когда в CMP entity определяется метод EJB Create необходино вернуть уникальный первичный ключ, чтобы контейнер мог создать запись в БД с этим идентификатором. S>Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?
Вернуть из ejbCreate null. В этом случае контейнер сам занимается генерацией ключа. Правда, при этом придется указать тип первичного ключа не Integer, а Object, поскольку контейнер сам займется выбором подходяшего (с его точки зрения) типа для ключа. Подробности в спецификации.
--
Дмитро
Re: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, secam, Вы писали:
S>Приветствую !
S>Есть такой вопрос... Когда в CMP entity определяется метод EJB Create необходино вернуть уникальный первичный ключ, чтобы контейнер мог создать запись в БД с этим идентификатором. S>Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?
Эта задача подробно описана в книге Floyd Marinescu — EJB Design Patterns. См. главу 5 Primary Key Generation Strategies. Для ее решения там предложено два подхода, которые не зависят ни от СУБД и поддерживаемых ею механизмов генерации уникальных ключей, ни от EJB-контейнера.
Тут прозвучало предложение о том, чтобы вообще не париться с этим и указать класс первичного ключа как Object, вот цитата:
>Вернуть из ejbCreate null. В этом случае контейнер сам занимается генерацией ключа. Правда, при этом >придется указать тип первичного ключа не Integer, а Object, поскольку контейнер сам займется выбором >подходяшего (с его точки зрения) типа для ключа. Подробности в спецификации.
Во-первых, любой метод ejbCreate<METHOD> класса компонента CMP Entity Bean согласно спецификации EJB 2.1 должен быть реализован так, чтобы возвращать null, см. главу 10 Entity Bean Component Contract for Container-Managed Persistence, пункт 10.5.2 Bean Provider’s Entity Bean Instance’s View, страница 188:
The implementation of the Bean Provider’s ejbCreate<METHOD> methods should be coded to return a null.[18]
В сноске 18 на той же странице есть следующее пояснение:
The above requirement is to allow the creation of an entity bean with bean-managed persistence by subclassing an entity bean with container-managed persistence.
Во-вторых, в спецификации ничего не сказано о том, что в случае, когда тип первичного ключа указан как Object, то "контейнер сам займется выбором подходяшего (с его точки зрения) типа для ключа". По спецификации это, практически, задача того, кто выполняет деплоймент, поскольку фактическую структуру первичного ключа задает он. Вот что сказано в спецификации на самом деле, см. главу 10 Entity Bean Component Contract for Container-Managed Persistence, пункт 10.8.3 Special Case: Unknown Primary Key Class, страница 222 и 223:
In special situations, the entity Bean Provider may choose not to specify the primary key class or the primary key fields for an entity bean with container-managed persistence. This case usually happens when the entity bean does not have a natural primary key, and/or the Bean Provider wants to allow the Deployer using the Container Provider’s tools to select the primary key fields at deployment time. The entity bean’s primary key type will usually be derived from the primary key type used by the underlying database system that stores the entity objects. The primary key used by the database system may not be known to the Bean Provider.
...
When defining the primary key for the enterprise bean, the Deployer using the Container Provider’s tools will typically add additional container-managed fields to the concrete subclass of the entity bean class (this typically happens for entity beans that do not have a natural primary key, and the primary keys are system-generated by the underlying database system that stores the entity objects). In this case, the container must generate the primary key value when the entity bean instance is created (and before ejbPostCreate is invoked on the instance.)
The primary key class is specified at deployment time in the situations when the Bean Provider develops an entity bean that is intended to be used with multiple back-ends that provide persistence, and when these multiple back-ends require different primary key structures.
В любом случае лично мое мнение состоит в том, чтобы не привязываться к механизмам СУБД, поскольку, как мне кажется, возможны проблемы при использовании различных сочетаний контейнеров и СУБД. Впрочем, если у кого-то есть другое мнение — поделитесь, интересно узнать, что думает народ.
Re: CMP: ejbCreate и получение уникального Primary KEY
Есть такой вопрос... Когда в CMP entity определяется метод EJB Create необходино вернуть уникальный первичный ключ, чтобы контейнер мог создать запись в БД с этим идентификатором.
Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?
В книжке нашел пример, который состоит в следующем ... для нахождения уникального PK типа Integer делается примерно следующее :
int i=0;
while (true) {
try {
entity = home.findByPrimaryKey(Integer>getInteger(null,i));
} catch (FinderException ex) {
break;
}
i++;
}
Таким образом при выходе из цикла получим уникальный id но у меня рука не поднимается использовать настолько корявый способ ... при том, что БД имеет средства AUTO INCREMENT и может сама давать уникальные значения при попытке записать с id=NULL и при этом гарантирует уникальность.
При работе вышеуказанного цикла, контейнеру приходится вызывать множество раз один и тот же запрос к базе данных и по сути перебирать ВСЮ базу, а это могут быть СОТНИ мегабайт !
Обращаюсь к профессионалам, дайте пожалуйста альтернативное решение ...
Re: CMP: ejbCreate и получение уникального Primary KEY
У меня специально сделан SessionBean, имеющий бизнес-метод BigInteger getPrimaryKey(), он ищет DataSource, выполняет запрос SELECT SEQ_MY.NEXTVAL FROM DUAL и возвращает полученный результат. При создании EntityBean'a просто обращаюсь к этому SessionBean'у и вытаскиваю следующий ключ. Выложу код если интересно.
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, Risotto, Вы писали:
R>Здравствуйте, secam, Вы писали:
S>>Обращаюсь к профессионалам, дайте пожалуйста альтернативное решение ...
R>Создаем запрос (в ejb-jar.xml):
R><ejb-ql>
R> SELECT MAX(s.id) FROM schema1 s
R></ejb-ql>
R>ну а потом вызываем сопоставленный find() метод.
оба решения обладают главным недостатком — они не являются потоко-безопасными
два одновременных create приведут к ошибке неуникальности первичного ключа в одном из них
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, dshe, Вы писали:
S>>Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?
D>Вернуть из ejbCreate null. В этом случае контейнер сам занимается генерацией ключа. Правда, при этом придется указать тип первичного ключа не Integer, а Object, поскольку контейнер сам займется выбором подходяшего (с его точки зрения) типа для ключа. Подробности в спецификации.
в подавляющем большинстве случаев подробности приходится искать в документации к используемому апп-серверу (см. формат ejb-<appservername>.xml), т.к. поддерживаемые способы генерации значения первичного ключа являются вендор-зависимыми
Re: CMP: ejbCreate и получение уникального Primary KEY
От:
Аноним
Дата:
16.05.05 10:41
Оценка:
GUID?
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
S>>Обращаюсь к профессионалам, дайте пожалуйста альтернативное решение ... S>>
R>Создаем запрос (в ejb-jar.xml): R>
R><ejb-ql>
R> SELECT MAX(s.id) FROM schema1 s
R></ejb-ql>
R>
R>ну а потом вызываем сопоставленный find() метод.
Идея великолепная ... единственная проблема EJB QL почему-то ругается на конструкцию MAX(..)
говорит дословно следующее:
Error parsing ejb-ql query: 'SELECT MAX(c.id) FROM ClientEJB AS c':
Expected 'object', path variable or 'distinct', not 'MAX' at position 8 ('MAX')
Дайте пожалуйста линк на какую — нибудь толковую доку по EJB QL, если есть. Буду очень признателен.
И в общем-то вопрос остается открытым ...
Единственное, что мне удалось узнать что есть встроенная возможность получать уникальный ключ у контейнера:
Для персистентности, управляемой контейнером, эти значения ключа могут генерироваться автоматически контейнером EJB. Чтобы использовать преимущества от этого свойства бин сущности должен удовлетворять следующим требованиям:
В дескрипторе развертывания класс первичного ключа определяется как java.lang.Object. Поле первичного ключа не задается.
В домашнем интерфейсе аргумент метода findByPrimaryKey должен быть java.lang.Object.
В классе бина сущности возвращаемый тип метода ejbCreate должен быть java.lang.Object.
В таких бинах сущностей значения первичного ключа находятся во внутреннем поле, которое доступно только контейнеру EJB. Вы не можете связать первичный ключ с персистентным полем или с любой другой переменной экземпляра. Но вы можете выбрать первичный ключ бина вызовом метода getPrimaryKey и вы можете найти бин вызовом его метода findByPrimaryKey.
Для меня это было новостью.
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, John_Headlong, Вы писали:
S>>Есть такой вопрос... Когда в CMP entity определяется метод EJB Create необходино вернуть уникальный первичный ключ, чтобы контейнер мог создать запись в БД с этим идентификатором. S>>Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?
J_H>Эта задача подробно описана в книге Floyd Marinescu — EJB Design Patterns. См. главу 5 Primary Key Generation Strategies. Для ее решения там предложено два подхода, которые не зависят ни от СУБД и поддерживаемых ею механизмов генерации уникальных ключей, ни от EJB-контейнера.
беда — в неэффективности генерации ключей без прямого использования поддержки со стороны СУБД (потери на задействовании нескольких уровней выше СУБД, хотя задача изначально на уровне СУБД уже, как правило, решена — либо в виде sequenses, либо в виде auto-increment)
т.е. в ситуации, когда таблица заполняется по факту ручной работы сравнительно небольшого количества операторов-пользователей программы, это еще терпимо, а если например, надо обрабатывать и логировать сообщения, поступающие с высокой плотностью, то этот генератор станет узким местом
сам пример в указанной, imho, больше содержит учебной информации для размышления, нежели применим на практике в серьезных приложениях
J_H>В любом случае лично мое мнение состоит в том, чтобы не привязываться к механизмам СУБД, поскольку, как мне кажется, возможны проблемы при использовании различных сочетаний контейнеров и СУБД. Впрочем, если у кого-то есть другое мнение — поделитесь, интересно узнать, что думает народ.
большинство СУБД имеет либо sequences, либо auto-increment. также в некоторых (для меня — экхотических) случаях применяются триггеры
зная об этом, ведущие производители контейнеров эти случаи уже так или иначе закрыли, для применения достаточно разбираться в конкретных форматах вендор-зависимых частей ejb-дескрипторов
так или иначе, а разработчики программы страдают меньше всех — потому что дескриптор настраивает DEPLOYER
но мне больше нравится подход hibernate — мы его используем вместо entity ejb. там есть несколько разных генераторов первичных ключей, в т.ч. поддержка sequences, auto-inc, а также поддержка автовыбора одного из этих 2х наиболее популярных способов в зависимости от используемой СУБД.
настройки же делаются исключительно в xml hibernate-мэппингов без нагрузки на исходный текст программы
Re[3]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, C0s, Вы писали:
C0s>беда — в неэффективности генерации ключей без прямого использования поддержки со стороны СУБД (потери на задействовании нескольких уровней выше СУБД, хотя задача изначально на уровне СУБД уже, как правило, решена — либо в виде sequenses, либо в виде auto-increment) C0s>т.е. в ситуации, когда таблица заполняется по факту ручной работы сравнительно небольшого количества операторов-пользователей программы, это еще терпимо, а если например, надо обрабатывать и логировать сообщения, поступающие с высокой плотностью, то этот генератор станет узким местом
Ну почему же этот способ неэффективен? Как раз в решении, описанном в книге, очень много внимания уделяется именно эффективности реализации механизма. Там ведь не тупой инкремент счетчика, который хранится в БД, а организовано кеширование диапазонов значений ключей, чтобы в подавляющем числе случаев генерация ключа сводилась к инкременту числа в памяти. Автор позаботился даже о тонкой расстановке транзакционных атрибутов, чтобы при массированном использовании механизма это не приводило к длительной блокировке конкурирующих транзакций. Поясните, пожалуйста, в чем вы видите неэффективность?
C0s>сам пример в указанной, imho, больше содержит учебной информации для размышления, нежели применим на практике в серьезных приложениях
А мне казалось, что книга под названием EJB Design Patterns предлагает решения распространенных практических проблем для использования как раз именно в серьезных приложениях. А что бы вы посоветовали почитать на затронутую тему?
C0s>большинство СУБД имеет либо sequences, либо auto-increment. также в некоторых (для меня — экхотических) случаях применяются триггеры C0s>зная об этом, ведущие производители контейнеров эти случаи уже так или иначе закрыли, для применения достаточно разбираться в конкретных форматах вендор-зависимых частей ejb-дескрипторов C0s>так или иначе, а разработчики программы страдают меньше всех — потому что дескриптор настраивает DEPLOYER
Это понятно, но где гарантия, что при переносе решения с одного сервера приложений на другой сервер приложений или при подмене одной СУБД другой СУБД не возникнет проблем? Средства генерации первичных ключей и все тонкости, что с ними связаны, практически не стандартизованы, здесь каждый производитель СУБД считает своим долгом отличиться, проявив тем самым свою "уникальность" на рынке. В случае возникновения таких проблем это уже затронет и разработчиков, а не только deployer'а. Приятность же кроссплатформенного решения как раз и состоит в том, что это гарантированный результат в любой конфигурации, разве нет? Причем эта кроссплатформенность как на уровне серверов приложений, так и на уровне СУБД. Причем последняя может вовсе не поддерживать никаких средств генерации уникальных ключей.
C0s>но мне больше нравится подход hibernate — мы его используем вместо entity ejb. там есть несколько разных генераторов первичных ключей, в т.ч. поддержка sequences, auto-inc, а также поддержка автовыбора одного из этих 2х наиболее популярных способов в зависимости от используемой СУБД. C0s>настройки же делаются исключительно в xml hibernate-мэппингов без нагрузки на исходный текст программы
Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.
Re[4]: CMP: ejbCreate и получение уникального Primary KEY
От:
Аноним
Дата:
17.05.05 15:51
Оценка:
Здравствуйте, John_Headlong, Вы писали:
C0s>>но мне больше нравится подход hibernate — мы его используем вместо entity ejb. там есть несколько разных генераторов первичных ключей, в т.ч. поддержка sequences, auto-inc, а также поддержка автовыбора одного из этих 2х наиболее популярных способов в зависимости от используемой СУБД. C0s>>настройки же делаются исключительно в xml hibernate-мэппингов без нагрузки на исходный текст программы
J_H>Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.
Ну если забыть о BMP, то всё равно есть довольно много преимуществ — и зачастую они перевешивают "стандартность" (которая тем более всё равно требует server-specific deployment descriptors)
1) Testability вне контейнера
2) Возможность использовать внутри сервера без EJB контейнера (e.g. Tomcat) если не нужны Session Beans. Или просто с отключенным EJB-container что ускоряет compile-deploy цикл.
3) Более мощный QL
4) Гибкость маппинга
5) Краткость
Regards,
Zis
Re[4]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, John_Headlong, Вы писали:
J_H>Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.
Ну, вот, приехали. Как минимум все обещают performance + скорость разработки. Так что не помнятно в чем преимущество не практичных стандартных решений по сравнению со сторонними — простыми и быстрыми.
Re[5]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, Blazkowicz, Вы писали:
B>Ну, вот, приехали. Как минимум все обещают performance + скорость разработки. Так что не помнятно в чем преимущество не практичных стандартных решений по сравнению со сторонними — простыми и быстрыми.
Практика показывает, что обещания зачастую оказываются откровенным враньем. Например фирма Microsoft на протяжении последних десяти лет пыталась убедить пользователей, что операционная система Windows — самая надежная и защищенная операционная система в мире. Тем не менее, любой здравомыслящий человек понимает, что это не более, чем миф.
Что касается рассматриваемого вопроса, то как вы оцениваете скорость разработки? Что стоит написать CMP Entity Bean? Ничего — это рутинная работа, которая может быть легко автоматизирована, потому что для создания CMP Entity надо знать лишь: название сущности, имена и типы полей. Все. Никакого кода, который бы потребовал мыслительных усилий человека, здесь не требуется. В чем здесь преимущество сторонних решений, где для создания сохраняемого объекта нужно то же самое?
Что касается производительности, то здесь нужны измерения, а не голословные утверждения, желательно с пояснением, почему результат такой, а не иной. У кого-нибудь есть такие результаты?
Re[5]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, Lucker, Вы писали:
L>Все что связано с Design Patterns косательно конкретной технологии это не про то как надо строить архитекуру, а про то как обходить проблеммы возникающие при реализации архитекруты используя данную конкретную технологию. Особенно это касается EJB.
Ну и? Вы просто поиграли словами и все. Так что с тем конкретным способом обойти проблемы, что изложен в указанной книге?
L>Кроссплатформенность на уровне серверов приложений (и уж тем более на уровне СУБД) — утопия. В большестве случаев такая кроссплатформенность не требуется. Большинство EE систем пишутся под заказ, где заказчик выложил круглую сумму денег за преобретенные АПП И БД сервера и выкладывать еще ему нету необходимости. L>Если пишется коробочный продукт и требуется кроссплатформенность, то достигается это все выделением непереносимого кода в отдельные интерфейсы и реализацей их для каждой требуемой платформы.
Если бы дело обстояло так, как говорите вы, то тогда никогда не возникло бы Java и J2EE, ибо этот язык и эта платформа — они просто пронизаны идеей переносимости, которая оправдывает любую сложность. Никогда не появилось бы того сонма подробнейших спецификаций, никогда не возникло бы вокруг них сообщеста, в рамках которого идет обсуждение и принимаются решения о будущем.
Во многом это справедливо и для СУБД: люди очень быстро осознают, что колбасЁрить кто во что горазд — ума много не надо. А потребность в совместимости и переносимости — объективная реальность.
Re[6]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, John_Headlong, Вы писали:
J_H>Практика показывает, что обещания зачастую оказываются откровенным враньем. Например фирма Microsoft на протяжении последних десяти лет пыталась убедить пользователей, что операционная система Windows — самая надежная и защищенная операционная система в мире. Тем не менее, любой здравомыслящий человек понимает, что это не более, чем миф.
Пример не к месту. Обещают не производители, а те кто хоть раз пользовался. Просто у меня тут практического опыта не много. Так что им поделится не могу.
J_H>Что касается рассматриваемого вопроса, то как вы оцениваете скорость разработки? Что стоит написать CMP Entity Bean? Ничего — это рутинная работа, которая может быть легко автоматизирована, потому что для создания CMP Entity надо знать лишь: название сущности, имена и типы полей. Все. Никакого кода, который бы потребовал мыслительных усилий человека, здесь не требуется. В чем здесь преимущество сторонних решений, где для создания сохраняемого объекта нужно то же самое?
Скорость разработки оценивается тем что работа с CMP/BMP порождает ряд трудностей и проблем (наподобие того с чего начался топик) на которые приходится искать решения. Это и есть время потраченое на разработку.
J_H>Что касается производительности, то здесь нужны измерения, а не голословные утверждения, желательно с пояснением, почему результат такой, а не иной. У кого-нибудь есть такие результаты?
И что CMP может предложить? Никакущую производительность зависящую от реализации контенера? Метрик не имею, но можно заглянуть:
Здравствуйте, John_Headlong, Вы писали:
J_H>Ну и? Вы просто поиграли словами и все. Так что с тем конкретным способом обойти проблемы, что изложен в указанной книге?
То что самый правильный способ обойти проблеммы связанные с EJB — не использовать EJB, пока это не потребуется. К счатью это не требуется так часто (я так понимаю единственный случай где оправдано использование EJB — это реализация true-распределенной архитекуры — то для чего они собственно и придуманы были, все остальные случаи надуманы и могут быть заменены более правильными технологиями).
L>>Кроссплатформенность на уровне серверов приложений (и уж тем более на уровне СУБД) — утопия. В большестве случаев такая кроссплатформенность не требуется. Большинство EE систем пишутся под заказ, где заказчик выложил круглую сумму денег за преобретенные АПП И БД сервера и выкладывать еще ему нету необходимости. L>>Если пишется коробочный продукт и требуется кроссплатформенность, то достигается это все выделением непереносимого кода в отдельные интерфейсы и реализацей их для каждой требуемой платформы.
J_H>Если бы дело обстояло так, как говорите вы, то тогда никогда не возникло бы Java и J2EE, ибо этот язык и эта платформа — они просто пронизаны идеей переносимости, которая оправдывает любую сложность. Никогда не появилось бы того сонма подробнейших спецификаций, никогда не возникло бы вокруг них сообщеста, в рамках которого идет обсуждение и принимаются решения о будущем.
Хочу тебя разочаровать — дело именно так и обстоит. Переносимость бывает разная, на разных уровнях. То что дает тебе Java — это переносимость на уровне host-платформы. Как только требования к приложению выходят за рамки предоставляемых JRE севрисов — в ход идет JNI, что сразу приводит к потере переносимости на этом уровне и необходимости выделять абстакции и реализовывать их для каждой требуемой платформы.
То что дает тебе J2EE — переносимость на уровне app сервера, реализующего ту или иную спеку. Так только приложению требуется нечто большее определенного в спецификации J2EE — в ход идет тот же прием и мы опять теряем переносимость приложения и обязаны обеспечивать ее сами. И так далее, для любого уровня.
Этот же принцип работает и на J2ME платформе (только достигается другими методами).
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Re[5]: CMP: ejbCreate и получение уникального Primary KEY
Здравствуйте, C0s, Вы писали:
C0s>в сравнении с типичными механизмами, предоставляемыми СУБД, этот — медленнее, потому что подменяет их с помощью довольно ресурсоемких технологий C0s>насколько медленнее сложно оценить, но для упомянутого мной примера с записями информации об обработанных сообщениях, поступающих с высокой плотностью, можно, например, такие моменты выделить: C0s>- обработчики будут кластеризованы, чтобы выдержать высокий поток, а вышеупомянутый генератор с кэшем либо будет некластеризуемым и станет узким местом, либо потребует усовершенствования и станет головной болью при деплойменте приложения, чтобы развести разные экземпляры генератора по диапазонам значений
А СУБД здесь почему не станет узким местом???
Кроме того, вспомним о том, что изначально этот механизм предназначен для использования как не просто генератор неких ключей, а как генератор ключей для CMP Entity Beans. То есть предполагается ИЗНАЧАЛЬНО, что приложение использует ресурсоемкие технологии в виде CMP Entity Beans. Приложения, о которых говорите вы, — это, согласитесь, спецслучай, заслуживающий спецсредств для реализации. Платформа J2EE, насколько понимаю я, никогда не позиционировалась как платформа для приложений реального времени.
C0s>- даже с кэшем все равно генерация происходит в своей транзакции (requires new). думаю, не все аппсерверы смогут обеспечить оптимальное начало/конец глобальной транзакции даже в случае с отсутствием взаимодействия с БД, а если смогут — то потребуются усилия при деплойменте по настройке использования менеджера транзакции
Об оптимизации распределенных транзакций, ограниченных одним источником данных, сказано в спецификации XA, глава 2 Model and Definitions, пункт 2.3 Transaction Completetion and Recovery, подпункт 2.3.2 Protocol Optimisations на странице 8:
· Read-only
An RM can respond to the TM’s prepare request by asserting that the RM was not asked to update shared resources in this transaction branch. This response concludes the RM’s involvement in the transaction; the Phase 2 dialogue between the TM and this RM does not occur. The TM need not stably record, in its list of participating RMs, an RM that asserts a read-only role in the global transaction. However, if the RM returns the read-only optimisation before all work on the global transaction is prepared, global serialisability1 cannot be guaranteed. This is because the RM may release transaction context, such as read locks, before all application activity for that global transaction is finished.
· One-phase Commit
A TM can use one-phase commit if it knows that there is only one RM anywhere in the DTP system that is making changes to shared resources. In this optimisation, the TM makes its Phase 2 commit request without having made a Phase 1 prepare request. Since the RM decides the outcome of the transaction branch and forgets about the transaction branch before returning to the TM, there is no need for the TM to record stably these global transactions and, in some failure cases, the TM may not know the outcome.
Спецификация выпущена в декабре 1991 года. Думаю, эти соображения изначально учитываются разработчиками контейнеров, которые более глубоко понимают накладные расходы, связанные с глобальными транзакциями, чем мы с вами.
C0s>я имел в виду не всю книгу, в которой хватает нормальных мыслей, а только конкретный паттерн. не забывайте, что книга старая, а производители аппсерверов не сидят сложа руки
Можете что-то более новое посоветовать, где затронут этот вопрос?
C0s>гарантия именно в том, что типовых способов на стороне СУБД — 2: sequences или автогенерация (инкремент или применение триггера on insert) C0s>с точки зрения appserverа это: C0s>- либо запрос значения ключа перед вставкой (например, выполнение select, возвращающего следующее значение sequence) C0s>- либо запрос у СУБД получившегося в ней значения после вставки C0s>и то и другое — не более, чем настройки, которые достаточно вынести в ejb-дескриптор C0s>т.е. задача не такая уж большая, и производители аппсерверов беспокоятся о ее решении
Вы только что рассуждали о произволительности, а вот здесь получается, что на каждую вставку необходимо два обращения в БД: одно для извлечения очередного значения ключа, второе на собственно вставку. Именно эти вопросы рассматриваются в книге, именно поэтому, например, в предложенном там решении используется сессионный фасад для Entity-компонента, предоставляющего доступ к таблице, где хранятся очередные значения ключей всех сущностей. Этот сессионный фасад огранизует кеширование блоков кодового пространства, сводя всю операцию (в ПОДАВЛЯЮЩЕМ БОЛЬШИНСТВЕ случаев) к простому инкременту счетчика в памяти.
C0s>вообще, в серьезном приложении обычно приходится использовать jms, т.к. это и удачный инструмент для событийного по своей сути программирования, балансирует нагрузку, средство интеграции и т.п. .... естественно в связке с СУБД
При чем тут JMS??? Мы рассуждаем о генерации первичных ключей для CMP Entity Beans.
J_H>>Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.
C0s>это уже в поиск — на этом форуме есть отдельные нитки обсуждений hibernate vs entity ejb vs jdo и т.п. C0s>в контексте данного вопроса упомяну лишь, что hibernate удачнее, чем паттерн Флойда Маринеску, генерирует primary key values, потому что: C0s>- использует возможности базы напрямую без лишних слоев C0s>- знает массу диалектов баз, и пользователю hibernate не приходится сильно напрягаться
А у Флойда Маринеску не надо ничего знать ни о каких диалектах, а реализовав шаблон один раз, можно использовать его везде, ничего не настраивая. Так что запарок тоже не особо много, согласны?
C0s>- аппсервер-независим
Что здесь имеется в виду? Entity Beans прекрасно стандартизованы и поддерживаются всеми уважающими себя серверами приложений. Объем специфических для контейнера настроек не велик, он касается, прежде всего, отображения на структуру источника данных (для чего есть инструментарий) и настройки специфических параметров, влияющих на производительность, например размера пулов и таймаутов. Эти настройки на уровне EJB было глупо стандартизовывать, поскольку эта технология изначально оринетирована на поддержку источников данных самой различной природы — это производители только реляционные СУБД поддерживают, а на уровне платформы заложены более широкие возможности.