Brendan W.McAdams wrote:

I take it the CVS for that resides @ OpenEJB also

Yes


Thinking about what is done and how, I'm inclined to agree now on this point. Here's the big question:


Assuming the development efforts were willing to go in the direction of supporting this functionality, taking a general poll - is it better when dealing with things like supporting DB Generated keys to have a 'generic methodology' which is by definition less flexible (like what JBoss does), or a database specific support structure that relies upon coding a driver for each database type (Like BEA Weblogic does)? As much as it annoys me, my leaning is towards DB Specific support, with an optional 'generic' for unsupported DBs. Using each databases functionality for a feature like this gives you the most flexibility, and I can speak from experience that DBAs really consider it A Good Thing (tm) when you use DB specific features, and allow the database to manage key generation Angry Marauding DBAs == bad].


If you look at JBo$$ then they have a generic framework for plugging in vendor-specific implementations (the entity-commands). I rewrote most of that back in May for the 3.2.2 release so the (crap) code is mine but please be very careful with the IP issues.


There are a few basic techniques that need to be covered:
1) pre-insert generation. This might just be other implementations
   of o.o.n.entity.cmp.PrimaryKeyFactory that generate a PK somehow,
   inject it into the InstanceData and return the value. Examples
   could be a caching hi-lo key generator or something that issued
   a JDBC operation to get the value


I think if we go along the lines of database specific drivers, this is not the way to go.

You need both. The issue is not about using the database but of when you obtain the primary key value.


Some people want custom code - like your example of calling a stored procedure but have the container do it. This means work needs to be done before hand so the value is ready as insert time. A common scenario here is Oracle where people want to SELECT FROM DUAL/INSERT rather than use INSERT RETURNING.

This is also exactly how EJB works if you are not using an unknown pk - it is just the code is contained in ejbCreate and sets up the values in cmp-fields. So you have to support this mechanism for known keys, it is trivial to extend for key generation.



2) insert-side effect, where the value is generated as a consequence of performing the insert operation. Examples would be a MySQL auto- increment, JDBC getGeneratedKeys(), or Oracle with INSERT-RETURNING. The simple solution (KISS) is to always insert between ejbCreate and ejbPostCreate but that can mean some transactions insert then immediately update; the more complex solution would be to defer the insert for as long as possible, but that means being able to cope and reference to an EJB whose identity is not known. A compromise would be to delay until after ejbPostCreate which at least gives the user the chance to initialize any CMRs. This should be selectable by simply defining alternative VOPs for the create.


This is absolutely, IMNSHO the best route to go.

As I said, I think you need both.

<snip/>
I see two primary methods:

1) Something similar to JBoss' "unknown-pk" method - essentially, declare that the primary key will be database generated, and that it is a field of type 'X'. There then could be a section in the geronimo-cmp-rdbms.xml that declares a block of SQL or functions that must be called post-insert to find out the generated key. I'm not sure however just how 'optimal' this could be.

2) The Weblogic route. Declare in the geronimo-cmp-rdbms.xml file that the primary key is auto-generated on insert, and give specifics on what the database is. This would require of course that we have drivers for the major RDBMs, and document how to setup and interface their key generation methods within the CMP descriptors. Albeit less generic, I think this is the best route personally - I'm not sure I have enough experience to make that declaration however.


> Mind pointing me in the right direction on this?

The EJB spec defines "unknown pk" as any EJB where the prim-key-class is java.lang.Object. It has to be generic as the app doesn't know what type of key the container will generate (int, Timestamp, String, ...) JBo$$ adds stuff that allows you to override the values set by the bean in ejbCreate (or not set) but IMO that is bogus - if the bean set a value then that should be the one used, but at that point the app knows the type.

The simplest approach would be to have the deployer choose which VOP impl to use for the create method and have a config option on that VOP which says which impl of PrimaryKeyFactory to use. The choice of VOP allows you to configure pre-insert or insert-side-effect approaches, and the choice of factory impl allows you to choose a key generation strategy (either generic, vendor-specific, or even application supplied code).

I would start by having a look at the CMPContainer and CMPOperationFactory impls in OpenEJB - there are two create VOPs already. I would also recommend starting with the code and work out what you need to have the deployer build (IoC remember), and only at the end define the XML needed by the deployer.

--
Jeremy

/*************************
 * Jeremy Boynes
 * Partner
 * Core Developers Network
 *************************/

Reply via email to