Re: DatabaseContextDelegate + Compound Primary Keys that Include Foreign Keys (+INHERITANCE!!!)
Re: DatabaseContextDelegate + Compound Primary Keys that Include Foreign Keys (+INHERITANCE!!!)
- Subject: Re: DatabaseContextDelegate + Compound Primary Keys that Include Foreign Keys (+INHERITANCE!!!)
- From: Robert B.Hanviriyapunt <email@hidden>
- Date: Fri, 13 Jun 2008 12:03:46 -0500
Yes it seems the problem lies in the sub-relationship entity:
Company --(relationships[propagatesKeys=Y])-->> Product
SubProduct is a sub-entity to Product
thus:
Company <--(parent[cpkFkCompanyID])-- Product
Company <--(parent[cpkFkCompanyID])-- SubProduct
I have a sample project that illustrates this.
My attempts to determine what is actually happening has led me to a
few conclusions:
On a normal toMany (no inheritance), it works because primary keys
are resolved IN-ORDER based on propagates.
Once you introduce the inheritance on the destination object, it
fails to get primary keys ...
It seems that it does not resolve the primary keys in-order because
it does not respect or perhaps not know about the propagates to the
sub-entity.
On Jun 11, 2008, at 1:34 PM, Robert B. Hanviriyapunt wrote:
Yep. I figured that out yesterday (that I needed to set propagate
on all child/parent-relationships in sub-entities to Person. But I
still get the error about the EmployerEmployeeRelationship not
getting a primary key. I'm still verifying/investigating tho.
Thanks for helping btw. :D
= Robert =
On Jun 11, 2008, at 1:16 PM, Chuck Hill wrote:
On Jun 11, 2008, at 10:30 AM, Robert B.Hanviriyapunt wrote:
I think I actually HAVE an issue! But it needs further
verification.
Firstly, I forgot to mention versions and stuff. I'm on WO5.3.
Ok so my situation has more levels of complexity, namely
INHERITANCE!
1. My model has child Entities (single-table)
2. I'm dealing with a join/assignment table/Entity (many-to-many)
3. This Entity has child Entities whose primary key generation is
failing
So the more exact description of my problem is:
Person <--(parent)-- Relationship --(child)--> Person
MalePerson <--(parent)-- ParentChildRelationship --(child)-->
MalePerson
FemalePerson <--(parent)-- ParentChildRelationsihp --(child)-->
FemalePerson
MalePerson <--(parent)-- EmployerEmployeeRelationship --(child)--
> FemalePerson
Relationship <<--(parentRelationships)-- Person --
(childRelationships)-->> Relationship
This represents the different entities, they are sub-entities of
their logical entities, the sub-entities have their 'type'
attribute set appropriately, and the generic parent and child
relationships are defined at the top-Entity. The Relationship
classes are NOT maintained by EOF -- they are the problematic
compound primary key entities that are failing to get primary
keys in the following code:
EOEditingContext ec = new EOEditingContext();
MalePerson person1 = EOUtilities.createAndInsertInstance
( ec, "MalePerson" );
FemalePerson person2 = EOUtilities.createAndInsertInstance
( ec, "FemalePerson" );
EmployerEmployeeRelationship relationship =
EOUtilities.createAndInsertInstance( ec,
"EmployerEmployeeRelationship" );
relationship.addObjectToBothSidesOfRelationshipWithKey
( person1, "parent" );
relationship.addObjectToBothSidesOfRelationshipWithKey
( person2, "child" );
ec.saveChanges();
So the issue continues. Still no solution. Still testing.
It sounds like you have a modeling problem. Are all the
relationships class properties? Are the relationships into
EmployerEmployeeRelationship marked a Propogate Primary Key?
Chuck
= Robert =
Begin forwarded message:
From: Robert B. Hanviriyapunt <email@hidden>
Ok I'm feeling a bit foolish now ... I forgot to check
propagates primary key.
Ok I haven't fixed my problem yet ... but i'm gettin there. I
still think there's an issue somewhere.
= Robert =
On Jun 10, 2008, at 1:17 PM, Robert B. Hanviriyapunt wrote:
Ok, my bad. I did NOT correctly modify the project to work w/
normal EOF EO_PK_TABLE key generation.
Ok so it is now working w/o the Delegate and w/ straight
Integer keys. Will try the a delegate next.
= Robert =
On Jun 10, 2008, at 1:00 PM, Robert B. Hanviriyapunt wrote:
I'm sorry, I know everyone's at WWDC, but I really really
really need help on this one! I usually don't ask for help
because I can figure most stuff out, but man, this is driving
me nuts!
Somebody please ... help! I can be on the phone, do a Yugma,
whatever!
= Robert =
On Jun 10, 2008, at 11:53 AM, Robert B. Hanviriyapunt wrote:
Ok I really really hope someone can help me with this problem:
I have an existing database which my app has been coded with
a DatabaseContextDelegate to handle primary key generation.
I model all Entities such that primary keys and foreign keys
are NOT generated (getters or setters) in the class files.
My DatabaseContextDelegate is as follows:
public class DatabaseContextDelegate1 extends Object {
protected static Object utilValueForKey( Object object,
String key )
{
try {
return NSKeyValueCoding.Utility.valueForKey
( object, key );
}
catch ( NSKeyValueCoding.UnknownKeyException e )
{
NSLog.err.appendln
( "DatabaseContextDelegate1.utilValueForKey: e = " + e );
e.printStackTrace();
NSLog.err.appendln( "returning null ..." );
return null;
}
}
// --- EODatabaseContext.Delegate methods --
public NSDictionary databaseContextNewPrimaryKey
( EODatabaseContext databaseContext,
Object object,
EOEntity entity )
{
String debugPrefix =
"DatabaseContextDelegate1.databaseContextNewPrimaryKey: ";
// get primary key attributes (description of them)
from entity (description of) requesting new primary key(s)
NSArray primaryKeyAttributes =
entity.primaryKeyAttributes();
// if *NOT* EXACTLY ONE primary key attribute,
// return primary key dictionary for object and
primary key attributes
// NOTE: may return null if object does not have
values for ALL primary key attributes, thus
// allowing someone else (superclass) to handle
primary keys
if ( primaryKeyAttributes.count() != 1 )
{
NSDictionary primaryKeyDictionary =
primaryKeyDictionaryForObjectAndPrimaryKeyAttributes( object,
primaryKeyAttributes );
return primaryKeyDictionary;
}
// NOTE: at this point primary key attributes contain
EXACTLY ONE primary key attribute
// get description of first (and only) primary key
attribute
EOAttribute primaryKeyAttribute = (EOAttribute)
primaryKeyAttributes.objectAtIndex(0);
if ( primaryKeyAttribute.adaptorValueType() !=
EOAttribute.AdaptorBytesType )
{
// We support only number keys, so call the
superclass
return null;
}
// setup variables for further processing
EOAdaptorChannel channel = null;
NSDictionary primaryKeyDictionary = null;
try
{
databaseContext.lock();
channel = databaseContext.availableChannel
().adaptorChannel();
if ( ! channel.isOpen() )
channel.openChannel();
NSDictionary row = null;
try
{
EOSQLExpressionFactory factory =
new EOSQLExpressionFactory
( databaseContext.adaptorContext().adaptor() );
EOSQLExpression getRowExpr =
factory.expressionForString( "SELECT top 1 VALUE FROM
vNewUUID" );
channel.evaluateExpression( getRowExpr );
row = channel.fetchRow();
channel.cancelFetch();
}
catch ( Throwable localException ) {
channel.cancelFetch();
}
if ( row != null )
{
NSData newUUID = (NSData)row.objectForKey
( "VALUE" );
if ( newUUID != null )
primaryKeyDictionary = new NSDictionary
( (Object)newUUID, (Object)primaryKeyAttribute.name() );
else
NSLog.err.appendln( debugPrefix + "got
NULL newUUID for object " + object );
}
else NSLog.err.appendln( debugPrefix + "could not
set keys for object " + object );
}
catch ( Throwable ex ) {
System.err.println( ex.toString() );
}
finally
{
if ( channel.isOpen() && channel.isFetchInProgress
() )
channel.cancelFetch();
databaseContext.unlock();
}
// NOTE: may return null allowing someone else
(superclass) to handle primary keys
return primaryKeyDictionary;
}
// --- utility ---
public NSDictionary
primaryKeyDictionaryForObjectAndPrimaryKeyAttributes
( Object object,
NSArray primaryKeyAttributes )
{
String debugPrefix =
"DatabaseContextDelegate1.primaryKeyDictionaryForObjectAndPrimar
yKeyAttributes: ";
int primaryKeyAttributeCount =
primaryKeyAttributes.count();
// initialize "got all keys" to TRUE (to be set to
FALSE if one is found missing)
boolean gotAllKeys = true;
// initialize empty primary key dictionary
NSMutableDictionary primaryKeyDictionary = new
NSMutableDictionary();
// loop thru primary key attributes
for ( int x = 0 ; x < primaryKeyAttributeCount ; x++ )
{
// get next (primary key) attribute
EOAttribute attribute = (EOAttribute)
primaryKeyAttributes.objectAtIndex(x);
// get attribute name
String attributeName = attribute.name();
// get value from object for attribute by
attribute name
Object valueFromEO = utilValueForKey( object,
attributeName );
// if the object has a value, add it to the
primary key dictionary
// otherwise, flag "got all keys" as FALSE
if ( valueFromEO != null )
primaryKeyDictionary.setObjectForKey
( valueFromEO, attributeName );
else
{
System.out.println( debugPrefix +
"attributeName = " + attributeName + " ... no value from
EO ... setting gotAllKeys to FALSE" );
gotAllKeys = false;
}
}
// if we got values for ALL keys from the object,
// return the primary key dictionary
if ( gotAllKeys )
{
NSLog.debug.appendln( debugPrefix + "returning
primary key " + primaryKeyDictionary + " from object " +
object );
return primaryKeyDictionary;
}
// NOTE: at this point we did NOT get values for ALL
keys from the object ...
// We support only simple primary keys, data keys are
handled by superclass
// thus DO NOT return the primary key dictionary,
instead return NULL (nothing)
NSLog.err.appendln( debugPrefix + "could not set keys
for object " + object );
return null;
}
}
It's all straight forward and works for single primary keys.
Where it has problems is when a compound primary key element
is a foreign key (a relationship). I think I need the
primaryKeyDictionaryForObjectAndPrimaryKeyAttributes function
to correctly build the primary key dictionary, but I don't
know how to do it, especially with the primary key components
being foreign keys (used in relationships that are set, of
course). I simplified the test case:
Company:
pkID (binary)
*name (String)
Product:
cpkFkCompanyID (binary)
*cpkCode (String)
*name (String)
*only these items have diamonds on them in EOModeler
Company <--->> Product
default Product. cpkCode value is "xxx"
EODatabaseContext.setDefaultDelegate( new
DatabaseContextDelegate1() );
EOEditingContext ec = new EOEditingContext();
EOEnterpriseObject company =
EOUtilities.createAndInsertInstance( ec, "Company" );
EOEnterpriseObject product =
EOUtilities.createAndInsertInstance( ec, "Product" );
product.addObjectToBothSidesOfRelationshipWithKey
( company, "company" );
product.takeValueForKey( "xxx", "cpkCode" );
ec.saveChanges();
Sounds simple enough right?
Here's my error:
DatabaseContextDelegate1.primaryKeyDictionaryForObjectAndPrimary
KeyAttributes: attributeName = cpkFkCompanyID ... no value
from EO ... setting gotAllKeys to FALSE
[2008-06-10 11:18:33 CDT] <main>
DatabaseContextDelegate1.primaryKeyDictionaryForObjectAndPrimary
KeyAttributes: could not set keys for object {values =
{Company = "<com.webobjects.eocontrol.EOGenericRecord e2350a
<EOTemporaryGlobalID: 0 0 -64 -88 2 1 0 0 -40 42 1 0 0 0 1 26
115 69 -122 118 -65 -101 100 1>>"; cpkCode = "xxx"; }; this =
"<com.webobjects.eocontrol.EOGenericRecord abcd5e
<EOTemporaryGlobalID: 0 0 -64 -88 2 1 0 0 -40 42 2 0 0 0 1 26
115 69 -122 118 -65 -101 100 1>>"; }
<-- (2)
DatabaseContextDelegate1.primaryKeyDictionaryForObjectAndPrimary
KeyAttributes:
<-- (1) DatabaseContextDelegate1.databaseContextNewPrimaryKey:
[2008-06-10 11:18:33 CDT] <main> A fatal exception occurred:
Adaptor com.webobjects.jdbcadaptor.JDBCAdaptor@609812 failed
to provide new primary keys for entity 'Product'
[2008-06-10 11:18:33 CDT] <main>
java.lang.IllegalStateException: Adaptor
com.webobjects.jdbcadaptor.JDBCAdaptor@609812 failed to
provide new primary keys for entity 'Product'
at
com.webobjects.eoaccess.EODatabaseContext.prepareForSaveWithCoor
dinator(EODatabaseContext.java:5885)
at
com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesInE
ditingContext(EOObjectStoreCoordinator.java:409)
at com.webobjects.eocontrol.EOEditingContext.saveChanges
(EOEditingContext.java:3226)
at Application.<init>(Application.java:31)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0
(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance
(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance
(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance
(Constructor.java:494)
at java.lang.Class.newInstance0(Class.java:350)
at java.lang.Class.newInstance(Class.java:303)
at com.webobjects.appserver.WOApplication.main
(WOApplication.java:323)
at Application.main(Application.java:16)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke
(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke
(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at com.webobjects._bootstrap.WOBootstrap.main
(WOBootstrap.java:71)
If anyone has ANY suggestions, please email me as soon as
possible!
Thanks!
= Robert =
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40global-village.net
This email sent to email@hidden
--
Practical WebObjects - for developers who want to increase their
overall knowledge of WebObjects or who are trying to solve
specific problems.
http://www.global-village.net/products/practical_webobjects
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden