Discussion:
[castor-dev] One to many relation
Lukas Lang
2009-08-06 15:32:22 UTC
Permalink
Hey everybody,

I'm facing a problem when trying to map a one to many relation.

Imagine the following: A Parent entity references a List of Child
entities. The mapping is defined as follows:

<mapping>
<class name="org.castor.cpa.test.lazycollection.Child" identity="id">
<map-to table="lazy_collection_child" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
</class>
<class name="org.castor.cpa.test.lazycollection.Parent" identity="id">
<map-to table="lazy_collection_parent" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="children" type="org.castor.cpa.test.lazycollection.Child"
lazy="false" collection="arraylist">
<sql many-key="parent_id" />
</field>
</class>
</mapping>

when executing the following statements:

Parent parent = new Parent();
parent.setId(1);
Child child1 = new Child();
child1.setId(1);
Child child2 = new Child();
child2.setId(2);
parent.setChildren(Arrays.asList(child1, child2));

// Persist entities.
_db.setAutoStore(true);
_db.begin();
_db.create(parent);
_db.commit();
_db.setAutoStore(false);

The create operation fails because the insert statement is as follows:
INSERT INTO lazy_collection_child (id) VALUES (1);

Hence, Castor results in:

java.sql.SQLIntegrityConstraintViolationException: Column 'PARENT_ID'
cannot accept a NULL value.: Column 'PARENT_ID' cannot accept a NULL
value. at
org.castor.cpa.persistence.sql.keygen.NoKeyGenerator.executeStatement(NoKeyGenerator.java:212)

My general questions are:

Why would it not be possible to map a one to many relation only by
specifying a key column?

The Castor JDO docu does not take care of this issue. It only shows
bidirectional one to many. Has noone ever requested that feature?

Ralf, Ahmad: Any ideas, since you are rewriting SQL stmt generation?

Regards,
Lukas

PS: I'm facing this behavior with 1.2, 1.3 and 1.3.0.1-SNAPSHOT.




---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
r***@syscon.eu
2009-08-06 17:10:32 UTC
Permalink
Hi Lukas,

as far as I recall castor docs at the moment, they say that castor only supports bidirectional relations. While I know that some sorts of unidirectional ralations work they are not documented.

There is an very old issue to add support for unidirectional relations which currently is assigned to me. I intendet to write some test cases to find out under which conditions unidirectioanl relations work and at which they do not.

To my knowledge insert statements are only part of the problem. I think main part need to be done at Class- and FieldMolder. One thing you could try is to allow null for the foreign key column as it may be possible that castor will update the record inserted with the correct parent_id.

Ahmad only reorganizes current codebase around generation of SQL statements. His focus is to keep current functionallity but after his refactoring it should be much easier to add new features.

We can discuss this issue in more details once I'm back from holiday begin of next week.

Regards
Ralf

Hey everybody,

I'm facing a problem when trying to map a one to many relation.

Imagine the following: A Parent entity references a List of Child
entities. The mapping is defined as follows:

<mapping>
<class name="org.castor.cpa.test.lazycollection.Child" identity="id">
<map-to table="lazy_collection_child" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
</class>
<class name="org.castor.cpa.test.lazycollection.Parent" identity="id">
<map-to table="lazy_collection_parent" />
<field name="id" type="integer">
<sql name="id" type="integer" />
</field>
<field name="children" type="org.castor.cpa.test.lazycollection.Child"
lazy="false" collection="arraylist">
<sql many-key="parent_id" />
</field>
</class>
</mapping>

when executing the following statements:

Parent parent = new Parent();
parent.setId(1);
Child child1 = new Child();
child1.setId(1);
Child child2 = new Child();
child2.setId(2);
parent.setChildren(Arrays.asList(child1, child2));

// Persist entities.
_db.setAutoStore(true);
_db.begin();
_db.create(parent);
_db.commit();
_db.setAutoStore(false);

The create operation fails because the insert statement is as follows:
INSERT INTO lazy_collection_child (id) VALUES (1);

Hence, Castor results in:

java.sql.SQLIntegrityConstraintViolationException: Column 'PARENT_ID'
cannot accept a NULL value.: Column 'PARENT_ID' cannot accept a NULL
value. at
org.castor.cpa.persistence.sql.keygen.NoKeyGenerator.executeStatement(NoKeyGener
ator.java:212)

My general questions are:

Why would it not be possible to map a one to many relation only by
specifying a key column?

The Castor JDO docu does not take care of this issue. It only shows
bidirectional one to many. Has noone ever requested that feature?

Ralf, Ahmad: Any ideas, since you are rewriting SQL stmt generation?

Regards,
Lukas

PS: I'm facing this behavior with 1.2, 1.3 and 1.3.0.1-SNAPSHOT.




---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Werner Guttmann
2009-08-10 10:32:45 UTC
Permalink
Hi,

just a few observations, which are a result of a 1:1 meeting between
Lukas and myself:

a) Yes, there's no support for uni-directional 1:M relations.
b) What's worse, it won't be easy to introduce this.

Here's why:

a) Under normal circumstances, castor delays most operations until
commit time. E.g. when you you delete an object by issueing
Database.delete(), the actual SQL statement is issued at a very late
stage, but definitely not immediately after you have called the delete()
method.

b) The same is true for changes at commit time, where the change
detection logic only takes place at the end of the transaction.

c) For database.create() unfortunately, this is not the case. In other
words, Database.create() will cause SQL statements to be issued against
the database - and that's as part of the call hierarchy of
database.create(). This is BAD.

All in all, this is a serious design flaw of Castor, as much as I hate
to say this .. ;-).

Regards
Werner
Post by r***@syscon.eu
Hi Lukas,
as far as I recall castor docs at the moment, they say that castor
only supports bidirectional relations. While I know that some sorts
of unidirectional ralations work they are not documented.
There is an very old issue to add support for unidirectional
relations which currently is assigned to me. I intendet to write some
test cases to find out under which conditions unidirectioanl
relations work and at which they do not.
To my knowledge insert statements are only part of the problem. I
think main part need to be done at Class- and FieldMolder. One thing
you could try is to allow null for the foreign key column as it may
be possible that castor will update the record inserted with the
correct parent_id.
Ahmad only reorganizes current codebase around generation of SQL
statements. His focus is to keep current functionallity but after his
refactoring it should be much easier to add new features.
We can discuss this issue in more details once I'm back from holiday begin of next week.
Regards Ralf
Hey everybody,
I'm facing a problem when trying to map a one to many relation.
Imagine the following: A Parent entity references a List of Child
<mapping> <class name="org.castor.cpa.test.lazycollection.Child"
identity="id"> <map-to table="lazy_collection_child" /> <field
name="id" type="integer"> <sql name="id" type="integer" /> </field>
</class> <class name="org.castor.cpa.test.lazycollection.Parent"
identity="id"> <map-to table="lazy_collection_parent" /> <field
name="id" type="integer"> <sql name="id" type="integer" /> </field>
<field name="children"
type="org.castor.cpa.test.lazycollection.Child" lazy="false"
collection="arraylist"> <sql many-key="parent_id" /> </field>
</class> </mapping>
Parent parent = new Parent(); parent.setId(1); Child child1 = new
Child(); child1.setId(1); Child child2 = new Child();
child2.setId(2); parent.setChildren(Arrays.asList(child1, child2));
// Persist entities. _db.setAutoStore(true); _db.begin();
_db.create(parent); _db.commit(); _db.setAutoStore(false);
The create operation fails because the insert statement is as
follows: INSERT INTO lazy_collection_child (id) VALUES (1);
java.sql.SQLIntegrityConstraintViolationException: Column 'PARENT_ID'
cannot accept a NULL value.: Column 'PARENT_ID' cannot accept a
NULL value. at
org.castor.cpa.persistence.sql.keygen.NoKeyGenerator.executeStatement(NoKeyGener
ator.java:212)
Why would it not be possible to map a one to many relation only by
specifying a key column?
The Castor JDO docu does not take care of this issue. It only shows
bidirectional one to many. Has noone ever requested that feature?
Ralf, Ahmad: Any ideas, since you are rewriting SQL stmt generation?
Regards, Lukas
PS: I'm facing this behavior with 1.2, 1.3 and 1.3.0.1-SNAPSHOT.
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

Loading...