|
Home > Archive > Apache JDO Project > July 2006 > deletePersistent() automatically nulling out referring FKs?!
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 |
deletePersistent() automatically nulling out referring FKs?!
|
|
| Jörg von Frantzius 2006-07-05, 1:11 pm |
| Hi,
only now I realize that JPOX does some automatic nulling of FKs during
deletePersistent(), i.e. although I have an FK in the database, I'll
never run into a FK violation when deleting a record that is being
referred to!
In my package.jdo I have classes A and B referring to each other in a
1:1 relation:
<class name="AFragment" 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="BFragment" 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>
So table A has a column b_1to1_FK referring to B.
When I call deletePersistent() for a B object that is being referred to
by an A object, I see the following SQL:
[05 Jul 2006 16:23:46,483] DEBUG Request.java:70 - *UPDATE A SET
B_1TO1_FK=NULL WHERE A.B_1TO1_FK=<1>* -- 1 PS parameters
[05 Jul 2006 16:23:46,499] DEBUG Request.java:81 - Execution Time =
16 ms
[05 Jul 2006 16:23:58,656] DEBUG Request.java:70 - DELETE FROM B
WHERE ID = <1> -- 1 PS parameters
[05 Jul 2006 16:23:58,671] DEBUG Request.java:81 - Execution Time =
15 ms
The spec says "If deleting an instance would violate datastore integrity
constraints, it is implementation-defined whether an exception is thrown
at commit time, or the delete operation is simply ignored." JPOX does
neither of the two, but implements a third option. Is this intended to
be covered by the spec?
I'd think that this is dangerous behaviour, as the programmer might be
deleting objects without realizing the consequences. If the FK
violations occur, and consequently he must explicitly remove the object
from any existing relation before deleting it, then he knows what
information he is loosing exactly.
Regards,
Jörg
| |
| Craig L Russell 2006-07-05, 7:11 pm |
| | |
| Andy Jefferson 2006-07-06, 1:11 am |
| > JDO2 did intend to disallow the behavior you describe.
>
> Additionally, the metadata allows you to explicitly declare the
> behavior of the FK on delete.
>
> You could try explicitly setting the FK delete behavior to restrict,
> and see what happens:
>
> <field name="b_1to1" column="b_1to1_FK"
> persistence-modifier="persistent" >
> <foreign-key delete-action="restrict"/>
> </field>
>
> But even without this declaration, I think there is an issue with the
> described behavior.
Hi Jorg,
lets be specific here, there are actually 3 situations :-
1. You have dependent-field set. This will delete the other object
2. You have a FK included in your metadata (which you haven't). This will
leave it to the DB to do the work and throw errors if necessary
3. You have nothing specified (so the JDO impl would have been allowed to
create no FK in the datastore if doing schema generation - fortunately for
you JPOX creates it for you thinking that you had simply forgotten). In this
situation you get the FK nulling. Its been like this since day one and gives
the smoothest result for the user ... they want rid of that record so it is
removed without affecting other records.
--
Andy
| |
| Jörg von Frantzius 2006-07-06, 1:11 pm |
| Hello Craig,
that did the trick, I'm now seeing my constraint violation as expected,
thanks! So at least the delete-action="restrict" is not ignored.
Maybe the question should be: why does JPOX create FKs by default in
combination with a "|SET NULL" |deletion behaviour that is not
specified, at least not in the JDO2 spec? mysql 5 seems to have that
behaviour specifiable in FK constraints
<http://dev.mysql.com/doc/refman/5.0...onstraints.html>.
Also I'd bet it doesn't have that behaviour for one-many relationships,
so that's kinda inconsistent also.
Of course it's nice to have FKs created automatically, but then IMHO it
should have a default delete-action="restrict", as that's what you'd
expect when you see a FK in your schema...
Regards,
Jörg
Craig L Russell schrieb:
> Hi Jörg,
>
> JDO2 did intend to disallow the behavior you describe.
>
> Additionally, the metadata allows you to explicitly declare the
> behavior of the FK on delete.
>
> You could try explicitly setting the FK delete behavior to restrict,
> and see what happens:
>
> <field name="b_1to1" column="b_1to1_FK"
> persistence-modifier="persistent" >
> <foreign-key delete-action="restrict"/>
> </field>
>
> But even without this declaration, I think there is an issue with the
> described behavior.
>
> To my recollection, there are no TCK test cases for this.
>
> Craig
>
> On Jul 5, 2006, at 7:36 AM, Jörg von Frantzius 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!
>
>
| |
| Jörg von Frantzius 2006-07-06, 1:11 pm |
| Andy Jefferson schrieb:
>
> Hi Jorg,
>
> lets be specific here, there are actually 3 situations :-
>
> 1. You have dependent-field set. This will delete the other object
>
> 2. You have a FK included in your metadata (which you haven't). This will
> leave it to the DB to do the work and throw errors if necessary
>
> 3. You have nothing specified (so the JDO impl would have been allowed to
> create no FK in the datastore if doing schema generation - fortunately for
> you JPOX creates it for you thinking that you had simply forgotten). In this
> situation you get the FK nulling. Its been like this since day one and gives
> the smoothest result for the user ... they want rid of that record so it is
> removed without affecting other records.
>
Concerning 3., well, you know, there's people making mistakes (like
myself), and one might discover some day that relationship information
had been deleted for years, and that this information is suddenly badly
missing. Seriously, for some 1:n associations we were /very/ happy that
internal errors occured in our application due to FK constraints being
violated, as we forgot about certain relationships and that we never
want that information to get lost (even though we allowed the user to
try to delete it). So if that unspecified "SET NULL" or "remove from all
relationships upon deletion" feature had existed for 1:n also, we would
have been in trouble.
By looking at the code in DeleteRequest, it occurs to me that this
particular code would be the perfect place to keep 1:1 assocations from
degenerating into 1:n assocations, though!
Cheers,
Jörg
| |
| Jörg von Frantzius 2006-07-07, 1:11 pm |
| I just had a look at my test again and I discovered that indeed *JPOX
does ignore the delete-action="restrict"* for the 1:1 bidirectional
case. So upon deletion, objects will silently be removed from any 1:1
bidirectional relationships, and corresponding FK constraints will never
prevent such a deletion.
I created issue http://www.jpox.org/servlet/jira/browse/CORE-2895 for
this. Unfortunately yesterday I had been looking at the wrong test.
Regards,
Jörg
Jörg von Frantzius schrieb:
> Hello Craig,
>
> that did the trick, I'm now seeing my constraint violation as
> expected, thanks! So at least the delete-action="restrict" is not
> ignored.
>
> Maybe the question should be: why does JPOX create FKs by default in
> combination with a "|SET NULL" |deletion behaviour that is not
> specified, at least not in the JDO2 spec? mysql 5 seems to have that
> behaviour specifiable in FK constraints
> <http://dev.mysql.com/doc/refman/5.0...onstraints.html>.
> Also I'd bet it doesn't have that behaviour for one-many
> relationships, so that's kinda inconsistent also.
>
> Of course it's nice to have FKs created automatically, but then IMHO
> it should have a default delete-action="restrict", as that's what
> you'd expect when you see a FK in your schema...
>
> Regards,
> Jörg
>
> Craig L Russell schrieb:
>
| |
| Andy Jefferson 2006-07-07, 1:11 pm |
| > I just had a look at my test again and I discovered that indeed *JPOX
> does ignore the delete-action="restrict"* for the 1:1 bidirectional
> case. So upon deletion, objects will silently be removed from any 1:1
> bidirectional relationships, and corresponding FK constraints will never
> prevent such a deletion.
>
> I created issue http://www.jpox.org/servlet/jira/browse/CORE-2895 for
> this. Unfortunately yesterday I had been looking at the wrong test.
I'll await the testcase, and the spec clarification before touching it.
I will point out however that several TCK tests fail if I change that due to
FK constraints and the DB objecting to the deletion of an object since it
still has relationships hanging off it. For example
test(org.apache.jdo.tck.extents.CloseAll)javax.jdo.JDODataStoreException:
Delete request failed: DELETE FROM datastoreidentity0.PERSONS WHERE
DATASTORE_IDENTITY=?
[java] at
org.jpox.store.rdbms.request.DeleteRequest.execute(DeleteRequest.java:274)
[java] at
org.jpox.store.rdbms.table.ClassTable.delete(ClassTable.java:2493)
[java] at org.jpox.store.StoreManager.delete(StoreManager.java:902)
[java] at
org.jpox.state.StateManagerImpl. internalDeletePersistent(StateManagerImp
l.java:4206)
[java] at
org.jpox.state.StateManagerImpl.deletePersistent(StateManagerImpl.java:4161)
[java] at
org.jpox.AbstractPersistenceManager. internalDeletePersistent(AbstractPersist
enceManager.java:1393)
[java] at
org.jpox.AbstractPersistenceManager. deletePersistent(AbstractPersistenceMana
ger.java:1404)
[java] at
org.apache.jdo.tck.extents.ExtentTest.deleteEmployee(ExtentTest.java:200)
[java] at org.apache.jdo.tck.extents.CloseAll.test(CloseAll.java:61)
--
Andy
Java Persistent Objects - JPOX
|
|
|
|
|