|
Home > Archive > Apache JDO Project > May 2006 > Setting a 1:1 association with "mapped-by"
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Setting a 1:1 association with "mapped-by"
|
|
| Jörg von Frantzius 2006-05-17, 1:11 pm |
| Hello JDO experts,
when writing some JUnit test today I came across an interesting
phenomenon. I have two classes A and B with a 1:1 association between
them. The FK is put on class A, and the corresponding field on B has
"mapped-by" with the corresponding field on A (see metadata below).
Now when I have the following object graph:
and perform the operation
a1.setB_1to1(b2)
then I'd expect the object graph to look like the following:
In particular, I'd expect a2 not pointing to b2 anymore, as this clearly
is supposed to be is a 1:1 relationship. The implementation can
determine this being a 1:1 association, as there are two corresponding
fields, and consequently it should issue
"UPDATE A SET B_1TO1_FK=NULL WHERE B_1TO1_FK=2"
before
"UPDATE A SET B_1TO1_FK=2 WHERE ID=1"
to keep this being a 1:1 association.
However, what I end up with in the database is:
Does this really work as expected?
Here's the metadata:
<class name="A" identity-type="application" table="A"
detachable="true"
objectid-class="javax.jdo.identity.LongIdentity"
persistence-modifier="persistence-capable">
<inheritance strategy="new-table"/>
<version strategy="version-number" column="jdoversion"/>
<field name="id" primary-key="true"
persistence-modifier="persistent" value-strategy="sequence"
sequence="A_SEQ" >
<extension vendor-name="jpox"
key="key-database-cache-size" value="100"/>
</field>
<field name="*b_1to1*" column="b_1to1_FK"
persistence-modifier="persistent" >
</field>
</class>
<class name="B" identity-type="application" table="B"
detachable="true"
objectid-class="javax.jdo.identity.LongIdentity"
persistence-modifier="persistence-capable">
<inheritance strategy="new-table"/>
<version strategy="version-number" column="jdoversion"/>
<field name="id" primary-key="true"
persistence-modifier="persistent" value-strategy="sequence"
sequence="B_SEQ" >
<extension vendor-name="jpox"
key="key-database-cache-size" value="100"/>
</field>
<field name="*a_1to1*" *mapped-by="b_1to1"*
persistence-modifier="persistent" >
</field>
</class>
Regards,
Jörg
P.S.
I hope the pictures survived...
| |
| Jörg von Frantzius 2006-05-17, 1:11 pm |
| Eric Samson schrieb:
>
> /In particular, I'd expect a2 not pointing to b2 anymore, as this
> clearly is supposed to be is a 1:1 relationship. The implementation
> can determine this being a 1:1 association, as there are two
> corresponding fields, and consequently it should issue /
>
>
>
>
>
> Bu default, there is no 1:1 relationships either in Java or in RDBMS.
>
> If you want to insure this 1:1 bi-directional link you have to:
>
> * use some triggers in your db
> * use a JDO callback
> * do it cleanly in your set /getters in Java
> * use an ORM tool that can manage 1:1 bi-directional links
>
I see. Hm. Well. For this relationship, being "bidirectional" seems to
be equivalent to "being 1:1". Confusing.
Anyway, thanks for your answer!
Regards,
Jörg
| |
| Eric Samson 2006-05-17, 7:11 pm |
| In particular, I'd expect a2 not pointing to b2 anymore, as this clearly is supposed to be is a 1:1 relationship. The implementation can determine this being a 1:1 association, as there are two corresponding fields, and consequently it should issue
Bu default, there is no 1:1 relationships either in Java or in RDBMS.
If you want to insure this 1:1 bi-directional link you have to:
* use some triggers in your db
* use a JDO callback
* do it cleanly in your set /getters in Java
* use an ORM tool that can manage 1:1 bi-directional links
Best Regards,
.....: Eric Samson, Founder & CTO, xcalia
Service your Data!
________________________________
De : Jörg von Frantzius [mailto:joerg.von.frantzius@artnology.com]
Envoyé : mercredi 17 mai 2006 17:40
À : Apache JDO project
Cc : JDO Expert Group
Objet : Setting a 1:1 association with "mapped-by"
Hello JDO experts,
when writing some JUnit test today I came across an interesting phenomenon. I have two classes A and B with a 1:1 association between them. The FK is put on class A, and the corresponding field on B has "mapped-by" with the corresponding field on A (see metadata below).
Now when I have the following object graph:
and perform the operation
a1.setB_1to1(b2)
then I'd expect the object graph to look like the following:
In particular, I'd expect a2 not pointing to b2 anymore, as this clearly is supposed to be is a 1:1 relationship. The implementation can determine this being a 1:1 association, as there are two corresponding fields, and consequently it should issue
"UPDATE A SET B_1TO1_FK=NULL WHERE B_1TO1_FK=2"
before
"UPDATE A SET B_1TO1_FK=2 WHERE ID=1"
to keep this being a 1:1 association.
However, what I end up with in the database is:
Does this really work as expected?
Here's the metadata:
<class name="A" identity-type="application" table="A" detachable="true"
objectid-class="javax.jdo.identity.LongIdentity"
persistence-modifier="persistence-capable">
<inheritance strategy="new-table"/>
<version strategy="version-number" column="jdoversion"/>
<field name="id" primary-key="true" persistence-modifier="persistent" value-strategy="sequence" sequence="A_SEQ" >
<extension vendor-name="jpox" key="key-database-cache-size" value="100"/>
</field>
<field name="b_1to1" column="b_1to1_FK"
persistence-modifier="persistent" >
</field>
</class>
<class name="B" identity-type="application" table="B" detachable="true"
objectid-class="javax.jdo.identity.LongIdentity"
persistence-modifier="persistence-capable">
<inheritance strategy="new-table"/>
<version strategy="version-number" column="jdoversion"/>
<field name="id" primary-key="true" persistence-modifier="persistent" value-strategy="sequence" sequence="B_SEQ" >
<extension vendor-name="jpox" key="key-database-cache-size" value="100"/>
</field>
<field name="a_1to1" mapped-by="b_1to1"
persistence-modifier="persistent" >
</field>
</class>
Regards,
Jörg
P.S.
I hope the pictures survived...
| |
| Michael Bouschen 2006-05-17, 7:11 pm |
| Hi Jörg,
you can create an unique index on the FK in the database. This still
does not automatically update the other side of the relationship. But it
prevents storing unexpected relationship values into the database,
because the transaction would fail if a2 still refers b2.
The JDO implementation might support managing bidirectional
relationships in memory, but this is not mandated by the spec.
Regards Michael
> Eric Samson schrieb:
> I see. Hm. Well. For this relationship, being "bidirectional" seems to
> be equivalent to "being 1:1". Confusing.
>
> Anyway, thanks for your answer!
>
> Regards,
> Jörg
>
--
Michael Bouschen Tech@Spree Engineering GmbH
mailto:mbo.tech@spree.de http://www.tech.spree.de/
Tel.:++49/30/235 520-33 Buelowstr. 66
Fax.:++49/30/2175 2012 D-10783 Berlin
| |
| Craig L Russell 2006-05-18, 1:11 am |
| | |
| Jörg von Frantzius 2006-05-18, 1:11 pm |
| Craig L Russell schrieb:
> This result is surprising, considering that we added verbiage to the
> specification to address this issue. I'll take a closer look, but my
> intent was not to allow this scenario, either in the datastore or in
> memory *after the transaction commits*.
I'm glad that this case was intended to be covered, at least with a
JDOUserException being thrown, as the user could easily produce
inconsistent data in the database, i.e. a one-to-one relationship
degenerating into a one-to-many relationship. Maybe it would be useful
if a JDOUserException was thrown when a one-to-one relationship is
traversed and more than one related object is found (like with unique
Queries), as currently it is pretty much unspecified what should happen
in that case (unless some more "verbiage" has escaped me in the spec...)
Regards,
Jörg
>
> The way the spec was changed near the end of the cycle, both sides of
> a relationship need to be consistent, both in the datastore and in
> memory after a flush operation.
>
> This would be a candidate for a new TCK test to be released with a
> maintenance update of JDO.
>
> The result you obtained should only be possible if both sides of the
> relationship were mapped to different columns in the datastore.
>
> Craig
>
> <spec>
> If two relationships (one on each side of an association) are mapped
> to the same column,
> the field on only one side of the association needs to be explicitly
> mapped.
> The field on the other side of the relationship can be mapped by using
> the mapped-by at-
> tribute identifying the field on the side that defines the mapping.
> Regardless of which side
> changes the relationship, flush (whether done as part of commit or
> explicitly by the user)
> will modify the datastore to reflect the change and will update the
> memory model for con-
> sistency. There is no further behavior implied by having both sides of
> the relationship map
> to the same database column(s). In particular, making a change to one
> side of the relation-
> ship does not imply any runtime behavior by the JDO implementation to
> change the other
> side of the relationship in memory prior to flush, and there is no
> requirement to load fields
> affected by the change if they are not already loaded. This implies
> that if the RetainVal-
> ues flag or DetachAllOnCommit is set to true, and the relationship
> field is loaded, then
> the implementation will change the field on the other side so it is
> visible after transaction
> completion.
> Conflicting changes to relationships cause a JDOUserException to be
> thrown at flush
> time. Conflicting changes include:
> •adding a related instance with a single-valued mapped-by relationship
> field to
> more than one one-to-many collection relationship
> •setting both sides of a one-to-one relationship such that they do not
> refer to each
> other
> </spec>
>
> On May 17, 2006, at 12:07 PM, Michael Bouschen wrote:
>
>
> Craig Russell
> Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
> 408 276-5638 mailto:Craig.Russell@sun.com
> P.S. A good JDO? O, Gasp!
>
|
|
|
|
|