There is a good design pattern for this standard problem. It has been
published by Jonathan K. Weedon in the inprise.public.appserver newsgroup
2000-05-30 and I successfully adopted it for Jonas.
However there is a big problem with using it in Jonas, because for
performance reasons it depends on reuse of pooled stateless session beans, a
feature that is currently not supported by Jonas (as they told me it will be
supported in the next release - end of September 2000).
I have added the original posting as a binary attachment. Works great (if
you have reusable session beans), otherwise its inefficient, as it creates a
new session bean and updates one entity bean for every newKey() operation.
But it's thread-safe and completely independent of the database product. So
I would recommend adapting it and wait for September :-)
If you obtain a sequence from Oracle (or use any other db-specific key
generation facility), you have to make one additional query or update on the
database, which can be some performance drain if you create many beans at
once.
Best regards
Nikolaus Rumm
----- Original Message -----
From: "Phil Windley" <[EMAIL PROTECTED]>
To: <[EMAIL PROTECTED]>
Cc: <[EMAIL PROTECTED]>
Sent: Tuesday, June 27, 2000 1:34 AM
Subject: Re: Automatic counter
>
> Its faster to write, to be sure, but seems like its going to establish a
> new connection for every creation event. If those events are a small
> percentage of overall operations, it wouldn't be a problem, but I'm
> envisioning a system that has large numbers of creations, so this would be
> pretty expensive.
>
> Anyone else have ideas on getting a serial type (preferably from
> Postgresql) to work with in CMP to automatically create the PK for the
> bean?
>
> --phil--
>
> On Fri, 23 Jun 2000 11:16:16 -0600 [EMAIL PROTECTED] writes
> +--------------------
> | I couldn't get the serial type to work with CMP either. We added a
function
> like the following in each of our entity beans to use automatically
generated i
> d's from postgres (mytable_id_seq is a SEQUENCE):
> |
> | private Integer _getNewID()
> | throws SQLException
> | {
> | Connection conn=_dsource_.getConnection();
> | String sql="select nextval('mytable_id_seq')";
> | Statement stmt=conn.createStatement();
> | ResultSet rs=stmt.executeQuery(sql);
> | if(!rs.next())
> | throw new SQLException("Unable to get next sequence.");
> | Integer newid=new Integer(rs.getInt(1));
> | stmt.close();
> | conn.close();
> | return newid;
> | }
> |
> | I know this isn't an ideal solution, but it is faster than two beans..
> |
> | -Erik
> |
> |
> | At 09:55 AM 6/23/00 -0600, you wrote:
> | >
> | >I use Postgresql as well, but I couldn't figure out how to get
container
> | >managed entity beans to automatically set the primary key from the
SEQUENCE
> | >data type. I ended up creating a session bean to grab sequence numbers
> | >from the database each time I created an entity bean.
> | >
> | >Is there a better way? I'm all for it---creating two beans every time
I nee
> d
> | >one is not my idea of a good way to spend time.
> | >
> | >--phil--
> | >
> | >On Thu, 15 Jun 2000 08:33:58 -0400 "John M. Jones" writes
> | >+--------------------
> | >| Does your database support serial fields? These fields generate a
counter
> | >| for each record added. There's a trick to getting the next id when
calling
> | >| create(), but it eliviates coding a unique id generator. I use
PostgreSQL,
> | >| and it has a serial data type.
> | >|
> | >| Hope this helps,
> | >| John
> | >|
> | >| -----Original Message-----
> | >| From: [EMAIL PROTECTED]
> | >| [mailto:[EMAIL PROTECTED]]On Behalf Of Blasius Lofi
> | >| Dewanto
> | >| Sent: Thursday, June 15, 2000 5:13 AM
> | >| To: [EMAIL PROTECTED]
> | >| Subject: Automatic counter
> | >|
> | >|
> | >| Hi all,
> | >|
> | >| I just wonder, whether someone can help me...
> | >|
> | >| How can I implement a counter or a unique id
> | >| for my PrimaryKey in EJB? Because I don't want
> | >| to take care about it in my EJB.
> | >|
> | >| Another question:
> | >| When I quit from the EJBServer through the JonasAdmin,
> | >| I always get this exception:
> | >| Cannot unbind Datasources: java.lang.ClassCastException
> | >| Is this normal?
> | >|
> | >| Thank's a lot!
> | >| --
> | >| ---------------------------------------------------
> | >| Blasius Lofi Dewanto
> | >| ---------------------------------------------------
> | >| OpenUSS - Open Source University Support System
> | >| http://openuss.sourceforge.net
> | >| ---------------------------------------------------
> | >|
> | >|
> | >| __________________________________________________________________
> | >| Do You Yahoo!?
> | >| Gesendet von Yahoo! Mail - http://mail.yahoo.de
> | >| Yahoo! Auktionen - gleich ausprobieren - http://auktionen.yahoo.de
> | >|
> | >| ----
> | >| To unsubscribe, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "unsubscribe jonas-users".
> | >| For general help, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "help".
> | >|
> | >| ----
> | >| To unsubscribe, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "unsubscribe jonas-users".
> | >| For general help, send email to [EMAIL PROTECTED] and
> | >| include in the body of the message "help".
> | >|
> | >
> | >----
> | >To unsubscribe, send email to [EMAIL PROTECTED] and
> | >include in the body of the message "unsubscribe jonas-users".
> | >For general help, send email to [EMAIL PROTECTED] and
> | >include in the body of the message "help".
> | >
> | >
> |
> |
>
> ----
> To unsubscribe, send email to [EMAIL PROTECTED] and
> include in the body of the message "unsubscribe jonas-users".
> For general help, send email to [EMAIL PROTECTED] and
> include in the body of the message "help".
instructors_with_sequences.jar
Instructors with Sequences -------------------------- This example modifies the EJB example "instructors" to use primary key generation. The original instructors example required that the client fabricate the primary keys in order to construct the instructor instances. In this version, the client simply creates instructor entities, and the server takes care of fabricating a unique primary key. There are two EJBs which cooperate to provide unique primary keys. The first class is the "Sequence" entity bean. This class is simply a name/value pair, where the "value" indicates the current minimum non-allocated primary key value. The "name" is the name of the given sequence. Any number of uniquely named sequences may be stored in the same table. The Sequence entity bean is accessed via the SequenceGenerator stateless session bean. This session bean provides "block-oriented" access to the underlying entity bean (and thus to the underlying database). The first time a client asks for a unique primary key from the SequenceGenerator, the underlying Sequence is found or created, and its current minimum non-allocated primary key is atomically read and incremented by a specified block size. The SequenceGenerator then hands out incremental primary keys directly until the block size is reached, at which point it goes back to the Sequence to get the next block of numbers. There are a number of subtleties to this code: The method Sequence.getValueAfterIncrementingBy runs in its own transaction (e.g., its transaction-attribute is RequiresNew). Also the Sequence bean uses VerifyModifiedFields optimistic concurrency mode. These two settings ensure that getting the next block of sequence numbers is both fast (due to the fact that the method runs in its own transaction) and serialized (due to the fact that the transaction will fail to commit if the sequence was updated concurrently in a different transaction). Note that the serialization of the update could also be achieved by specifying the SERIALIZABLE isolation level on the JDBC connection. If this is done, this should probably be on a different JDB connection than the main work, since the SERIALIZABLE isolation level has a significant performance overhead if not needed. The SequenceGenerator is a stateless session bean which has state. Note that this is not a contradiction: in EJB, whether a session bean is stateful or stateless depends on whether the bean has "conversational" state, or has state relative to a particular client (or caller). In this case, the state of the stateless session bean is not dependent on the client (or caller). Thus, this is a valid use of a stateless session bean. Another peculiarity of the SequenceGenerator is its dependence on the fact that the EJB container does in fact pool stateless session beans. Note that in the EJB specification, it is not technically required that a stateless session bean be reused for sequential calls; it is legal to implement stateful session beans by instantiating a new object for every call. Were a container to do this, the performance of the SequenceGenerator would be unacceptable, because it would have to go back to the database for every primary key fabrication. It is likely that any viable EJB container will implement stateless session bean pooling, in which case the SequenceGenerator will have good performance. Configuration of the SequenceGenerator is done in the deployment descriptor. Two EJB environment variables are used to configure the bean: blockSize: The number of primary keys to allocate before going back to the database. retryCount: The call from the SequenceGenerator to the Sequence can fail, due to a concurrency collision. If a collision occurs, the SequenceGenerator will receive a TransactionRolledbackException from the call to Sequence.getValueAfterIncrementingBy. The retry count indicates how many times to try to access the Sequence before finally giving up. To run the example, see the readme for the "instructors" example.
