I have three tables in my database.
Table A - Master table
Table B - Dependent table containing foriegn key reference to table A
Table C - Dependent table containing foriegn key reference to table A
I have set the necessary foriegn key constraints in my backend.
Tables A and C are represented as Entity Beans with container managed persistance. The Create methods of both these tables are set to Transaction Requires.
I have created a session bean which performs some business process on these three tables.
I have a method in this session bean which is also set transaction requires and does the following steps.
1. Creates a record in table A, through the Entity Bean
2. Adds a dependent record in table B through JDBC
3. Adds a dependent record in table C through the Entity Bean
After executing the first step, an exception is thrown in the second step saying
"Foriegn key constraint is voilated".
Somehow the addition of the new record in table A is not visible to step 2.
If I remove the foriegn key constraints, it goes through because it does not make any checks, but if step 3 fails the transaction is rolled back only till step 2 and step 1 is committed.
One thing to be considered is that, if a dummy JDBC call is made before executing step 1, all the remaining three steps are considered in one transaction and it does not give any problems.
How can we achieve this without using the dummay JDBC call? What is the problem with this method? Is something missing?
Not had this myself, so I'm guessing. But I think you have a classic error in your code here. EJB's are not commited to the database in a predictable way. The container will cache them, and write them to the database in its own time.
So example, create an entity bean and so a select and it may not appear until some time later. The mix of ejb's and jdbc leads to these types of confusion.
I think the dummy jdbc is a red herring - fine it works with that app server in this case, but it may not with a different app server.
I think it is clearly defined in the spec, when the container has to commit the transaction. So with deployment set to Required the transaction is normally commited after ejbCreate. So here a main question is, whether the calls of 1. and 3. are wrapped also in an transactional method or not. And which connection do you use for call 2, which AppServer do you use and with which Options do you have deployed your Entity Beans.
I have a similar problem and would like to know the standard
way of doing this, if we use
Can I create a record in the master table and corressponding
records in the dependant tables all in one transaction ?
Right now, if I start a transaction and
1)add a record in the master table
2)add a record in the dependant tables
step 2 fails since the record added in step 1 is not visible in step 2
What would be the cleanest solution for JDBC and EJB ?
I just began to study J2EE .
Maybe my viewpoint was wrong .
I had read the SUN's J2EE ,it said
that table relationships could be
applied only to entity beans with
bean-managed persistence ,In that release ,
container-managed persistence did not
support table relationships .
I think that you must verify the application
server you were using .
I assume you make the jdbc call in the dependant objects and the master call is CMP. So if you have deployed the CMP entity bean with transaction mode Required and none wrapping transaction calls the create method then the container commits the transaction after ejbCreate/ejbPostCreate. Now you are able to add dependant rows in other tables with foreign key constraints to the master table, either with pure JDBC or also with CMP is of no importance, because the master row is commited in db. If you span a transaction over the insert of the master and the dependant rows with the dependant rows having a foreign key constraint to the master, it will fail, because the insert of the master isn't yet committed. So all depends on the concrete situation you have. The Required flag of the entity bean means that if you have started a transaction before the invocation of create then this transaction is also used for the creation (insert), but not commited after the creation. Only if none transaction is opened when calling the create method, there will be a new start (because the creation need one, which is set by flag Required) of a transaction and a Commit/Rollback at the end of the creation process.
Hope it clearifies
the problem here is.
we want all the operation in one and only one transaction. The updation to the master table should not get committed immediately, because all the dependent operations should be executed successfully before comitting. The problem here is the updation is done in a separate transaction context for the Entity bean and the JDBC call, hence the updates made to the master table is not visible to the JDBC transaction context. If they would have been in the same transaction, the updates would have been visible to step 2 even if it is not actually committed to the database.
In SUN's J2EE , about Transaction Attributes and Scope
is said that :
Transaction Client's Business Method's
Attribute Transaction Transaction
Required none T2
so , I think that you must begin a JDBC transaction in
client ,and call entity bean's Create method ....
The code like :
Please try it .
Moreover , you must remove the relationships because
container-managed persistence did not support table
relationships. If you want to use relationships , you
must use the Bean-managed .
greenhorse 2001/05/28 9:06