Hi Bruno,
whew! Sounds really complex, I try my best...
The first problem is the bidirectional reference between P1, P2. To
establish the FK (e.g. in P1 from P2) the referenced object (P2) have to
be persistent (else the PK of P2 will be 'null' and OJB will set FK in
P2 'null' too).
In CircularTest you can find examples for handling bidirectional
references (with DB constraints) e.g.
CircularTest#testBidirectionalWithConstraint()
http://svn.apache.org/viewcvs.cgi/db/ojb/branches/OJB_1_0_RELEASE/src/test/org/apache/ojb/odmg/CircularTest.java?view=markup
Say we only want to insert P1,P2. In this case you can do
new P1
new P2
flush (now both PK values exist)
set ref P1 to P2
set ref P2 to P1
commit
But there are other possibilities to store P1<-->P2 (see test-suite
examples)
Generally the ordering used by OJB first try to insert the 1:1
references of an object then the object itself and then the 1:n, m:n
references (if you don't like it, it's possible to disable OJB's ordering).
Now, with the OJB 1.0.4, circular or 1:1 cross references shouldn't
require flush().
This is not correct. It only mean that it is possible to handle
bidirectional references and the user should take a look in CircularTest
http://db.apache.org/ojb/docu/guides/odmg-guide.html#Circular-+and+Bidirectional+References
I don't known how it has been made, but i assume it works.
So, i consider now that OJB can find the good order (and the back on first
object to put last reference), however we still continue to create,
reference, unreference, delete with the DB sequence.
But i'm going to try to give you an example, that worked before 1.0.4. (with
flush()) and do not any more.
I think it worked "accidental". Before 1.0.4 when *not* using database
identity columns (like mysql supports) the PK's are created before the
object was stored to DB (create PK for P1 and P2, resolve references,
set FK, insert objects).
-consider the circular pair of objects P1 and P2 (1:1 relation
, cross-referenced)
-consider now that we have a "M"aster object, that have a collection
of "D"etails obects, themselves referencing an instance of P1. Let's call
master object M, and details objects D.
- consider a last refrence relation between P1 and M (the master)
So, all writing process is done like this (assume "new" is instanciating and
locking at the same time):
....
it's schematic but I believe there is all to explain.
Our first problem was, that, after commit, P1 was not referencing M in
database. I deduced that after a flush(), new locked objects (before flush)
can't reference new ones created before flush too (a second time). Humm,
strange... we check all code : No apparent mistakes.
Then, I found this about 1.0.4 releases notes [[OJB-18] - ODMG ordering
problem with circular/bidirectional 1:1 references]. Well, OJB finds the
good order now and close the circular schema, fine. So we tried to remove
[flush #2] and process worked.
After, i said to all my team to remove flush(). Everyone was happy ! And
after [flush #1] was removed, process crashed with the FK constraints P2 to
P1 (you known, the circular pair) . It seems ODMG (without any flush) does
not find the good order to solve a "far" circular pair. I don't known why at
all.
Sorry for the hassle. The explanation is given above. You should always
ask "when will the PK exist" -> after the object is inserted. So to set
the FK's of a P1<-->P2, P2 have to be persistent to assign the FK in P1
and P1 have to be persistent to assign the FK in P2 -> impossible to
find a order.
E.g. new P1, P2, set both references and then lock P1 or P2, OJB will
only resolve one reference, e.g. commit call--> set FK in P2 (P1 PK is
'null' --> FK 'null'), insert P2, set FK in P1 (PK of P1), insert P1.
Don't forget we have there a "double inside" circular reference (P1 & P2
inside M-D-P1 & P1-M). At first, i didn't think about resolve this
construction without 2 flushes minimum. And now, i have only one! Sorry for
headache, but i'm lost too.
Isn't it great?
For example, the code below should work too (with one flush)
> [tx.begin]
> - new M
> - loop of (D)
{ new D (assume that mean add D to list/collection in M)
D references M (think this should work ,but maybe this have be done
after flush too)
new P1 ,
D references P1
new P2 ,
flush() (now all PK of all object should exist)
P1 references P2 ,
P2 references P1)
P1 references M
> }
> [tx.commit]
>
I have an enourmous doubt about the other processes that still have flush
steps and work on an equivalent part of model (double circular).
Additional flush() calls should never cause problems. Flush only write
the current locked objects to DB.
Please, could you explain me the different ordering behaviours of ODMG?
See above (when ordering is enabled, first 1:1, object itself...). If
you disable ordering the order of objects is determined by the lock
calls (when implicit locking is disabled too).
And
when put a flush or not?
I can't give a rule for using flush. For best performance use it only
when needed (each flush call perform the object detection/ordering).
regards,
Armin
Thanks a lot.
References : OJB 1.0.4, ObjectDefaultImpl, ODMG transactions with "same
broker" queryObject methods (to possibly retrieve instanciated objects
before commit )
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]