CMP: ejbCreate и получение уникального Primary KEY
От: secam  
Дата: 14.05.05 19:15
Оценка:
Приветствую !

Есть такой вопрос... Когда в 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
От: Risotto Украина  
Дата: 14.05.05 22:27
Оценка: -1
Здравствуйте, secam, Вы писали:

S>Обращаюсь к профессионалам, дайте пожалуйста альтернативное решение ...

S>

Создаем запрос (в ejb-jar.xml):
<ejb-ql>
    SELECT MAX(s.id) FROM schema1 s
</ejb-ql>

ну а потом вызываем сопоставленный find() метод.
Кто-то сказал когда-то давно, что людям свойственно убивать тех, кого любишь. Что ж, верно и обратное.
Re: CMP: ejbCreate и получение уникального Primary KEY
От: dshe  
Дата: 15.05.05 23:47
Оценка: 2 (1)
Здравствуйте, secam, Вы писали:

S>Приветствую !


S>Есть такой вопрос... Когда в CMP entity определяется метод EJB Create необходино вернуть уникальный первичный ключ, чтобы контейнер мог создать запись в БД с этим идентификатором.

S>Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?

Вернуть из ejbCreate null. В этом случае контейнер сам занимается генерацией ключа. Правда, при этом придется указать тип первичного ключа не Integer, а Object, поскольку контейнер сам займется выбором подходяшего (с его точки зрения) типа для ключа. Подробности в спецификации.
--
Дмитро
Re: CMP: ejbCreate и получение уникального Primary KEY
От: kostaky Россия  
Дата: 16.05.05 05:38
Оценка:
Здравствуйте, secam, Вы писали:

У меня специально сделан SessionBean, имеющий бизнес-метод BigInteger getPrimaryKey(), он ищет DataSource, выполняет запрос SELECT SEQ_MY.NEXTVAL FROM DUAL и возвращает полученный результат. При создании EntityBean'a просто обращаюсь к этому SessionBean'у и вытаскиваю следующий ключ. Выложу код если интересно.
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
От: C0s Россия  
Дата: 16.05.05 09:38
Оценка:
Здравствуйте, 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
От: C0s Россия  
Дата: 16.05.05 09:44
Оценка:
Здравствуйте, dshe, Вы писали:

S>>Вопрос в том, как этот идентификатор получить, есть ли какие-то приличные алгоритмы ?


D>Вернуть из ejbCreate null. В этом случае контейнер сам занимается генерацией ключа. Правда, при этом придется указать тип первичного ключа не Integer, а Object, поскольку контейнер сам займется выбором подходяшего (с его точки зрения) типа для ключа. Подробности в спецификации.


в подавляющем большинстве случаев подробности приходится искать в документации к используемому апп-серверу (см. формат ejb-<appservername>.xml), т.к. поддерживаемые способы генерации значения первичного ключа являются вендор-зависимыми
Re: CMP: ejbCreate и получение уникального Primary KEY
От: John_Headlong  
Дата: 16.05.05 10:30
Оценка: 2 (1)
Здравствуйте, 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
От: Аноним  
Дата: 16.05.05 10:41
Оценка:
GUID?
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
От: John_Headlong  
Дата: 16.05.05 10:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>GUID?


В книге EJB Design Patterns этот подход рассмотрен. Скачать книгу и примеры к ней можно отсюда:

http://www.theserverside.com/books/wiley/EJBDesignPatterns/
Re[2]: Увы не работает ...
От: secam  
Дата: 16.05.05 12:10
Оценка:
Здравствуйте, Risotto, Вы писали:


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
От: kostaky Россия  
Дата: 16.05.05 12:25
Оценка:
SessionBean for generating BigDecimal ID:

/**
 * @author konstantin I. Ilyinov
 * @version $Revision: 1.0 $
 *
 * @ejb:bean name="ejb/fondskvee/SeqGen"
 *           display-name="Generates unique Identifier for an Entity"
 *           type="Stateless"
 *           local-jndi-name="ejb/fondskvee/SeqGenLocal"
 *           view-type="local"
 *           transaction-type="Container"
 *
 * @ejb:interface extends="javax.ejb.EJBObject"
 *                local-extends="javax.ejb.EJBLocalObject"
 *                generate="local"
 *
 * @ejb:env-entry name="FondDS" value="java:/FondDS"
 *
 * @ejb:resource_ref res-name="java:/FondDS"
 *
 * ejb:env-entry name="ejb/fondskvee/SeqGenLocal"
 *               value="ejb/fondskvee/SeqGenLocal"
 *
 * @ejb:permission unchecked="true"
 **/
public class SeqGenBean implements SessionBean
{
   private SessionContext mContext;

   // -------------------------------------------------------------------------
   // Methods
   // -------------------------------------------------------------------------

   /**
    * Create the Session Bean
    * @throws CreateException
    * @ejb:create-method view-type="local"
    **/
   public void ejbCreate() throws CreateException
   {
   }

   /**
    * Delivers the next sequence number from the given Sequence Name
    * @return long Next sequence number (PK = Id)
    * @throws RemoteException
    * @ejb:interface-method view-type="local"
    * @ejb:transaction type="Required"
    **/
   public BigDecimal getNextId()
   {
      Connection aConnection = null;
      Statement aStatement = null;
      try
      {
         Context lContext = new InitialContext();
         String lDataSourceName =
             (String) lContext.lookup("java:comp/env/FondDS");
         DataSource aSource =
             (DataSource) lContext.lookup( lDataSourceName );
         aConnection = aSource.getConnection();
         aStatement = aConnection.createStatement();
         String aSql = "select gen_id_seq.nextval from dual";
         ResultSet aResult = aStatement.executeQuery( aSql );
         BigDecimal lResult = new BigDecimal(0);
         if( aResult.next() ) {
            lResult = aResult.getBigDecimal( 1 );
         }else{
           throw new EJBException (
               "��� ���� ��������� � ���������");
         };
         return lResult;
      } catch( Exception ex ) {
         throw new EJBException (
             "��� ���������������� ����������������� " + ex.toString());
      }
      finally {
         try {
           if( aStatement != null ) aStatement.close();
           if( aConnection != null ) aConnection.close();
         } catch( Exception e ) { }
      }
   }

   /**
    * Delivers the next sequence number from the given Sequence Name
    *
    * @return long Next sequence number (PK = Id)
    *
    * @ejb:interface-method view-type="local"
    *
    * @ejb:transaction type="Required"
    **/
   public BigDecimal getNextUid() throws EJBException
   {
     try{
       // ����� � �� ����
       Properties properties = System.getProperties();
       String strForHash = properties.get("java.library.path").toString() +
                           properties.get("user.dir").toString() +
                           properties.get("os.name").toString();
       double hash = java.lang.Math.abs( (double)strForHash.hashCode() );
       double helpDouble = Math.log(hash)*Math.log(Math.E)/Math.log(12);
       double helpProp = (helpDouble - Math.floor(helpDouble)) +
                                           Math.floor(helpDouble) % 3;
       hash = Math.pow(10, helpProp);
       // ����� � �� ����       double random = hash*Math.pow(10, 12) +
                            Math.round(Math.random()*Math.pow(10, 12));
       return new BigDecimal(random);
     }catch(Exception ex){
       throw new EJBException(
           "��� �����UID � ��� � ������: \n" +
           "�����, �����, ��. \n" +
           "���� � ���: " +
           ex.toString());
     }
   }


   /**
    * Describes the instance and its content for debugging purpose
    *
    * @return Debugging information about the instance and its content
    **/
   public String toString()
   {
      return "SequenceGeneratorBean [ " + " ]";
   }

   // -------------------------------------------------------------------------
   // Framework Callbacks
   // -------------------------------------------------------------------------

   public void setSessionContext( SessionContext aContext ) throws EJBException
   {
      mContext = aContext;
   }

   public void ejbActivate() throws EJBException
   {
   }

   public void ejbPassivate() throws EJBException
   {
   }

   /**
    * @ejb:permission unchecked="true"
    * @throws EJBException
    */
   public void ejbRemove() throws EJBException
   {
   }

}


Using SeqGenBean in the EntityBean (I guess it would be clear):


package fondskvee.entity;
/*
 * $Id: EmployeeBean.java,v 1.3 2003/03/04 04:48:48 topping Exp $
 */
import java.math.BigDecimal;
import javax.naming.InitialContext;
import javax.ejb.*;

import fondskvee.interfaces.SeqGenLocalHome;
import fondskvee.interfaces.SeqGenLocal;
import replication.interfaces.*;

/**
 * @ejb.bean name="YearBeginBalanceCMPEntity"
 *           type="CMP"
 *           local-jndi-name="ejb/fondskvee/YearBeginBalanceCMPEntityLocal"
 *           cmp-version="2.x"
 *           view-type="local"
 *
 * @ejb.persistence table-name="YEAR_BEGIN_BALANCE"
 * @jboss.persistence table-name="YEAR_BEGIN_BALANCE" create-table="false"
 *
 * @ejb:ejb-ref ejb-name="ejb/fondskvee/SeqGen" ref-name="SeqGen"
 *
 * @ejb.value-object match="*"
 *
 * @ejb.finder
 *    method-intf="LocalHome"
 *    query="SELECT OBJECT(o) FROM YearBeginBalanceCMPEntity o where o.idPred = ?1 AND o.idMesto = ?2 "
 *    result-type-mapping="Local"
 *    signature="java.util.Collection findAllForPredMesto(java.math.BigDecimal idPred, java.math.BigDecimal idMesto)"
 *
 * @jboss.query
 *    signature="java.util.Collection findAllForPredMesto(java.math.BigDecimal idPred, java.math.BigDecimal idMesto)"
 *    query="SELECT OBJECT(o) FROM YearBeginBalanceCMPEntity o where o.idPred = ?1 AND o.idMesto = ?2 ORDER BY o.year DESC "
 *
 * @ejb.finder
 *    method-intf="LocalHome"
 *    query="SELECT OBJECT(o) FROM YearBeginBalanceCMPEntity o where o.idPred = ?1 AND o.idMesto = ?2 AND o.year = ?3 "
 *    result-type-mapping="Local"
 *    signature="java.util.Collection findAllForPredMestoYear(java.math.BigDecimal idPred, java.math.BigDecimal idMesto, java.sql.Timestamp year)"
 *
 * @jboss.query
 *    signature="java.util.Collection findAllForPredMestoYear(java.math.BigDecimal idPred, java.math.BigDecimal idMesto, java.sql.Timestamp year)"
 *    query="SELECT OBJECT(o) FROM YearBeginBalanceCMPEntity o WHERE o.idPred = ?1 AND o.idMesto = ?2 AND o.year = ?3 ORDER BY o.year DESC "
 *
 * @ejb:pk class="fondskvee.entity.CommonPK" generate="false"
 *
 * @author Konstantin I. Ilyinov
 * @version $Revision: 1.0 $ $Date: 09/03/2004 $
 * @ejb:permission unchecked="true"
 */
public abstract class YearBeginBalanceCMPEntityBean implements EntityBean
{
    /**
     * @return idPred.
     * @ejb.interface-method view-type="local"
     * @ejb.persistent-field
     * @ejb.persistence column-name="id_pred"
     * @ejb.pk-field
     */
    public abstract java.math.BigDecimal getIdPred();
    /**
     * @param idPred
     */
    public abstract void setIdPred(java.math.BigDecimal idPred);

    /**
     * @return id.
     * @ejb.interface-method view-type="local"
     * @ejb.persistent-field
     * @ejb.persistence column-name="id"
     * @ejb.pk-field
     */
    public abstract java.math.BigDecimal getId();
    /**
     * @param idPpred
     */
    public abstract void setId(java.math.BigDecimal id);

    /**
     * @return id_mesto.
     * @ejb.interface-method view-type="local"
     * @ejb.persistent-field
     * @ejb.persistence column-name="id_mesto"
     */
    public abstract java.math.BigDecimal getIdMesto();
    /**
     * @param idMesto
     * @ejb.interface-method view-type="local"
     */
    public abstract void setIdMesto(java.math.BigDecimal idMesto);

    /**
     * @return year.
     * @ejb.interface-method view-type="local"
     * @ejb.persistent-field
     * @ejb.persistence column-name="year"
     */
    public abstract java.sql.Timestamp getYear();
    /**
     * @param year
     * @ejb.interface-method view-type="local"
     */
    public abstract void setYear(java.sql.Timestamp year);

    /**
     * @return gos_reserv_zakach.
     * @ejb.interface-method view-type="local"
     * @ejb.persistent-field
     * @ejb.persistence column-name="gos_reserv_yb"
     */
    public abstract java.math.BigDecimal getGosReservYb();
    /**
     * @param gosReservYb
     * @ejb.interface-method view-type="local"
     */
    public abstract void setGosReservYb(java.math.BigDecimal gosReservYb);

    /**
     * @ejb:create-method
     */
    public CommonPK ejbCreate(fondskvee.interfaces.YearBeginBalanceCMPEntityData data) throws CreateException {
      try {
        InitialContext initialContext = new InitialContext();
        SeqGenLocalHome seqGenLocalHome =
            (SeqGenLocalHome)initialContext.lookup("ejb/fondskvee/SeqGenLocal");
        SeqGenLocal seqGenLocal = seqGenLocalHome.create();
        BigDecimal nextId = seqGenLocal.getNextId();
        seqGenLocal.remove();
        setId(nextId);
        //---
        setIdPred( data.getIdPred() );
        setIdMesto( data.getIdMesto() );
        setYear( data.getYear() );
        setGosReservYb( data.getGosReservYb() );
      } catch (Exception ex) {
        new EJBException("��� ���� ��� ������� �� ������� ������� \n" + ex.toString());
      }
      return null;
    }

    /**
     * The container invokes this method to instruct the instance to synchronize its
     * state by storing it to the underlying database.
     * @ejb.interface-method view-type="local"
     */
    public void ejbStore() {}

}


Don't mind XDoclet markup, it's not important here
Re[3]: Увы не работает ...
От: C0s Россия  
Дата: 16.05.05 13:00
Оценка:
Здравствуйте, secam, Вы писали:

S>Идея великолепная ... единственная проблема EJB QL почему-то ругается на конструкцию MAX(..)


значит ejb-контейнер уровня спецификации ejb2.0, max и прочие агрегаты поддерживаются, начиная с ejb2.1
Re[2]: CMP: ejbCreate и получение уникального Primary KEY
От: C0s Россия  
Дата: 16.05.05 14:07
Оценка:
Здравствуйте, 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
От: John_Headlong  
Дата: 17.05.05 14:55
Оценка:
Здравствуйте, 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
От: Blazkowicz Россия  
Дата: 17.05.05 15:53
Оценка:
Здравствуйте, John_Headlong, Вы писали:

J_H>Лично я не совсем понимаю преимущества использования каких-то сторонних решений o/r mapping в серверных приложениях вместо стандартного средства — Entity Beans. В чем они? Клиентские приложения — это совсем другое дело.


Ну, вот, приехали. Как минимум все обещают performance + скорость разработки. Так что не помнятно в чем преимущество не практичных стандартных решений по сравнению со сторонними — простыми и быстрыми.
Re[4]: CMP: ejbCreate и получение уникального Primary KEY
От: Lucker Беларусь http://lucker.intervelopers.com/
Дата: 17.05.05 16:52
Оценка: 5 (1)
Здравствуйте, 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
От: C0s Россия  
Дата: 17.05.05 18:09
Оценка: 5 (1)
Здравствуйте, 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[5]: CMP: ejbCreate и получение уникального Primary KEY
От: John_Headlong  
Дата: 18.05.05 13:02
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Ну, вот, приехали. Как минимум все обещают performance + скорость разработки. Так что не помнятно в чем преимущество не практичных стандартных решений по сравнению со сторонними — простыми и быстрыми.


Практика показывает, что обещания зачастую оказываются откровенным враньем. Например фирма Microsoft на протяжении последних десяти лет пыталась убедить пользователей, что операционная система Windows — самая надежная и защищенная операционная система в мире. Тем не менее, любой здравомыслящий человек понимает, что это не более, чем миф.

Что касается рассматриваемого вопроса, то как вы оцениваете скорость разработки? Что стоит написать CMP Entity Bean? Ничего — это рутинная работа, которая может быть легко автоматизирована, потому что для создания CMP Entity надо знать лишь: название сущности, имена и типы полей. Все. Никакого кода, который бы потребовал мыслительных усилий человека, здесь не требуется. В чем здесь преимущество сторонних решений, где для создания сохраняемого объекта нужно то же самое?

Что касается производительности, то здесь нужны измерения, а не голословные утверждения, желательно с пояснением, почему результат такой, а не иной. У кого-нибудь есть такие результаты?
Re[5]: CMP: ejbCreate и получение уникального Primary KEY
От: John_Headlong  
Дата: 18.05.05 13:09
Оценка:
Здравствуйте, Lucker, Вы писали:

L>Все что связано с Design Patterns косательно конкретной технологии это не про то как надо строить архитекуру, а про то как обходить проблеммы возникающие при реализации архитекруты используя данную конкретную технологию. Особенно это касается EJB.


Ну и? Вы просто поиграли словами и все. Так что с тем конкретным способом обойти проблемы, что изложен в указанной книге?

L>Кроссплатформенность на уровне серверов приложений (и уж тем более на уровне СУБД) — утопия. В большестве случаев такая кроссплатформенность не требуется. Большинство EE систем пишутся под заказ, где заказчик выложил круглую сумму денег за преобретенные АПП И БД сервера и выкладывать еще ему нету необходимости.

L>Если пишется коробочный продукт и требуется кроссплатформенность, то достигается это все выделением непереносимого кода в отдельные интерфейсы и реализацей их для каждой требуемой платформы.

Если бы дело обстояло так, как говорите вы, то тогда никогда не возникло бы Java и J2EE, ибо этот язык и эта платформа — они просто пронизаны идеей переносимости, которая оправдывает любую сложность. Никогда не появилось бы того сонма подробнейших спецификаций, никогда не возникло бы вокруг них сообщеста, в рамках которого идет обсуждение и принимаются решения о будущем.

Во многом это справедливо и для СУБД: люди очень быстро осознают, что колбасЁрить кто во что горазд — ума много не надо. А потребность в совместимости и переносимости — объективная реальность.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.