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: Chuck Hill <email@hidden>
- Date: Wed, 11 Jun 2008 16:26:19 -0700
On Jun 11, 2008, at 1:13 PM, Robert B.Hanviriyapunt wrote:
Hey Chuck,
Would you be willing to test out my test app that illustrates my
issue? I'm on WO5.3+MySQL but I think it can work on any version
(it's quite basic).
I am more than busy for the rest of this month. If you remind me in
July, I will see if I have time.
Also, I don't work with Xcode projects any more. I probably have it
installed, but I don't care to launch it.
If this really turns out to be an issue, where might I submit this
for consideration for fixing WO?
bugreporter.apple.com
Chuck
Attachment: CpkFkTest2.zip (WO/Xcode project)
<CpkFkTest2.zip>
Begin forwarded message:
From: "Robert B. Hanviriyapunt" <email@hidden>
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.primaryKeyDictionaryForObjectAndPrima
ryKeyAttributes: ";
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.primaryKeyDictionaryForObjectAndPrimar
yKeyAttributes: attributeName = cpkFkCompanyID ... no value
from EO ... setting gotAllKeys to FALSE
[2008-06-10 11:18:33 CDT] <main>
DatabaseContextDelegate1.primaryKeyDictionaryForObjectAndPrimar
yKeyAttributes: 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.primaryKeyDictionaryForObjectAndPrimar
yKeyAttributes:
<-- (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.prepareForSaveWithCoo
rdinator(EODatabaseContext.java:5885)
at
com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesIn
EditingContext(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
--
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