[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Newsgroup Home]
|
[news.eclipse.rt.eclipselink] Order of mapping resolution
|
- From: t.denley@xxxxxxxxxx (Tom Denley)
- Date: Tue, 26 Aug 2008 14:32:34 +0000 (UTC)
- Newsgroups: eclipse.rt.eclipselink
- Organization: Eclipse
- User-agent: NewsPortal/0.36 (http://florian-amrhein.de/newsportal)
I am observing some interesting side-effects when using back-references
where part of the foreign key is qualified by a grand-parent in the
relationship. This is fairly in-depth, but I will do my best to explain it
succinctly.
I have a three-tier one-to-many hierarchy, described by the following
tables. Each table is keyed on a unique sequence-generated ID, and a
string code which splits the schema vertically.
GRANDPARENT (GRANDPARENT_ID, CODE)
PARENT (PARENT_ID, CODE)
CHIILD (CHILD_ID, CODE)
My object model for this domain gives each object its own identifier, but
stores the code on the grandparent only.
GrandParent
+ int identifier
+ String code
+ Collection<Parent> children
Parent
+ int identifier
+ GrandParent backRef
+ Collection<Child> children
Child
+ int identifier
+ Parent backRef
I map this through EclipseLink (We use the POJO ORM API as we came from
TopLink) using direct-to-field mappings for the identifier fields; batch
read one-to-many mappings for the forward going relationships; and
one-to-one mappings for the back-references.
This appears to work fine, but I noticed that in some scenarios fetches
were retrieving Parent objects whose Child objects were missing.
Debugging through the EclipseLink code, I noticed that for some
one-to-many relationships, EclipseLink is trying to pull child records
(from the pool of previously batch-read child candidates) using a correct
parent sequence number key, but a code of null. Looking further into this,
I discovered that EclipseLink is deriving the code by walking up the
back-reference to the GrandParent, but that this back-reference hadn't
been populated yet and was null. It appears that, for the mapping to work
correctly, the backRef property of each domain object must be the first
one to be populated, before the children property is addressed.
Looking in more detail at the way in which EclipseLink populates its
relational mappings reveals the reason for the erratic behaviour we were
observing. The order in which EclipseLink processes relational mappings is
deemed to be unimportant, and is casually achieved by iterating over the
result of a call to descriptor.getMappings() in the
buildAttributesIntoObject method in
org.eclipse.persistence.internal.descriptors.ObjectBuilder. This simply
returns the key-set of the Map of relationships (keyed by their
descriptors), and hence the order is arbitrarily determined by the hash
values of the descriptors and the hashing function of the JVM. Small
changes to our mappings were causing these hash values to change, and
subsequently the order of relational mapping population to change.
Arguably, this is both a bug in EclipseLink and an oversight in our
domain. Clearly, nobody in EclipseLink has ever considered the order of
population of relational descriptors to be important. There are no efforts
in the code to intelligently calculate the order, and there is no evidence
of any exposure of that order to the user through the EclipseLink IDE. We
should therefore consider that, although entirely achievable, it is
incorrect to build a domain in such a way that the order of relational
mapping evaluation becomes important.
The resolution for us, therefore, has been to re-architect our domain
objects so that the code is propagated throughout, and to adjust the
EclipseLink mappings to make use of these de-normalised codes so as to
prevent the need for back-references to be populated first. However, to me
this represents a pollution of our domain, and for this reason I am
posting here to see if anybody else has experienced similar problems, or
if anyone connected with EclipseLink would like to make a comment.
Regards,
Tom