Pere Torrodellas had a question about Identity keys, WebLogic and EJB CMP CMR as follows: (I thought I would post my answer here in case someone has a similar question they can find the answer with google and javaranch) "I'm trying to develop a CMP bean on a DB table that has a column defined as "auto increment", i.e. I don't set any value for this attribute in ejbCreate() and the DB manager sets it when the row is inserted. In order to get the value assigned to the column in the same client method that created it, I invoke a finder that retrieves the just created Bean by looking for another column value. To my dismay, the contents of the "auto increment" attribute is still null, which suggests that either the container has not yet performed the insert in the DB, or it performs a first search in its storage instead of accessing the persistent media. How can I force the container to immediately store the bean in the DB and refresh its data to get the automatically generated value? I suppose I could do it with a BMP (right?), but I'd rather use a CMP if possible." Here is my response
I read your question, and the first thing that popped in my mind was which app server are you using.... The app server you are you using can really impact how to handle auto increment ids. I hope they fix this part of the spec. up before EJB 2.2. Some EJB containers handle auto Ids transparently (e.g. Resin EE). Some EJB containers do no handle them at all. And, Some App servers require special mojo in the configuration files... I saw that you stated you are using WebLogic 6.1. WebLogic 6.1 uses the special mojo configuration file approach. (Hey can I identify that as a pattern... the special mojo pattern.... probably not) In your cmp mapping file (weblogic-cmp-rdbms-jar.xml) You will need to add one of these <automatic-key-generation> <generator-type>NAMED_SEQUENCE_TABLE</generator-type> <generator-name>CUSTOMER_SEQUENCE_TABLE</generator-name> <key-cache-size>10</key-cache-size> </automatic-key-generation>
There are several generator types depending on what database you are using. For example there is one specific to Oracle, and one Specific to MS SQL Server. I don't know why they don't have one specific to the IDENTIY keyword which is standard SQL 92 but they don't. MS SQL Server uses the IDENTIY keyword, Oracle 8 does not, but most other RDBMS servers do (DB2, MYSQL, Access, HyperSonic SQL, Cloudscape and so on) so you can try this approach with non MS SQL Server. If possible use the NAMED_SEQUENCE_TABLE for the generator.... it is the most portable. This is a hard sell if you are in an Oracle shop and you using Sequences in that case use the Oracle Sequence option. Refer to the weblogic docs for more information on <generator-type>s.
Here is what the DDL would look like for the NAMED_SEQUENCE_TABLE approach for a simple Customer EJB.
-- customer -- customer has many orders create table TBL_CUSTOMER ( CUSTOMER_ID INT primary key, FIRST_NAME varchar (25), LAST_NAME varchar (25), EMAIL varchar (100), PHONE varchar (25) ); create table CUSTOMER_SEQUENCE_TABLE(SEQUENCE integer); insert into CUSTOMER_SEQUENCE_TABLE values (100); Here is the rest of the mappings for this example to put it all into context....
<weblogic-rdbms-bean> <ejb-name>Customer</ejb-name> <data-source-name>mysource</data-source-name> <table-name>TBL_CUSTOMER</table-name> <!-- Study these mappings from the TBL_CUSTOMER columns to the Customer EJB cmp fields --> <field-map> <cmp-field>iD</cmp-field> <dbms-column>CUSTOMER_ID</dbms-column> </field-map> <field-map> <cmp-field>firstName</cmp-field> <dbms-column>FIRST_NAME</dbms-column> </field-map> <field-map> <cmp-field>lastName</cmp-field> <dbms-column>LAST_NAME</dbms-column> </field-map> <field-map> <cmp-field>phone</cmp-field> <dbms-column>PHONE</dbms-column> </field-map> <field-map> <cmp-field>email</cmp-field> <dbms-column>EMAIL</dbms-column> </field-map> <!-- TODO study this finder method -->
<weblogic-query> <query-method> <method-name>findByEmail</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <weblogic-ql>SELECT DISTINCT OBJECT(c) FROM Customer c where c.email = ?1</weblogic-ql> </weblogic-query>