• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: DatabaseContextDelegate + Compound Primary Keys that Include Foreign Keys
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: DatabaseContextDelegate + Compound Primary Keys that Include Foreign Keys


  • Subject: Re: DatabaseContextDelegate + Compound Primary Keys that Include Foreign Keys
  • From: "Robert B. Hanviriyapunt" <email@hidden>
  • Date: Tue, 10 Jun 2008 12:50:44 -0500

New development: it's not working even for plain eo_pk_table use!

I changed the DB to mysql and all the key components to integers.  I generated EO_PK_TABLE and removed the Delegate.  So basically modeled a more standard EOModel, except that I made a compound primary key that contains a foreign key.

and it's STILL broken!

= 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.primaryKeyDictionaryForObjectAndPrimaryKeyAttributes: ";

        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.primaryKeyDictionaryForObjectAndPrimaryKeyAttributes: attributeName = cpkFkCompanyID ... no value from EO ... setting gotAllKeys to FALSE
[2008-06-10 11:18:33 CDT] <main> DatabaseContextDelegate1.primaryKeyDictionaryForObjectAndPrimaryKeyAttributes: 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.primaryKeyDictionaryForObjectAndPrimaryKeyAttributes: 
<-- (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.prepareForSaveWithCoordinator(EODatabaseContext.java:5885)
at com.webobjects.eocontrol.EOObjectStoreCoordinator.saveChangesInEditingContext(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:

This email sent to email@hidden

  • Prev by Date: Re: WebObjects Nightly Builds and WOLips addition
  • Next by Date: Re: WebObjects Nightly Builds and WOLips addition
  • Previous by thread: Re: To Many to EOs w/ Compound Primary Keys that Include Reverse Foreign Key (+INHERITANCE!!!) -- FIX / WORK-AROUND
  • Next by thread: WebObjects Nightly Builds and WOLips addition
  • Index(es):
    • Date
    • Thread