Hi Andrus,

I'd go with the quick-fix for now (modeler) and maybe explore a better
solution in the future.  It is better to have them deal with a
safe/working restriction and not have potential errors.  Worst case,
if they want the artistId, they can follow the Artist relationship and
get the ID from there.  They can even add a cover method in
Painting.java:

public int getArtistId()
{
    return getArtist().getId();
}

mrg


On Wed, Oct 19, 2011 at 3:02 AM, Andrus Adamchik <[email protected]> wrote:
> Just coming of a few months (!) of low intensity debugging of a single 
> problem that looked as if Cayenne resets a non-null to-one relationship to 
> null. The FK would be not null in the DB, but all instances of a given object 
> across all DataContexts in a given app would return null for that one 
> relationship. Turned out this wasn't an obscure race condition, but rather 
> the following scenario:
>
> 1. Assume Artist and Painting with painting having to one relationship called 
> "artist", but also an ObjAttribute called "artistId"
> 2. For an existing Artist you may create a new painting, call "setArtist", 
> but don't set the "artistId" attribute explicitly.
> 3. Commit - that creates a valid record with non-null PAINTING.ARTIST_ID in 
> the db, but the object snapshot stored in DataRowStore suddenly has NULL for 
> "ARTIST_ID" key.
> 4. From here all DataContexts that fault this painting from the shared cache 
> will have NULL "artist" relationship, even though it is not null in the DB.
>
> The actual behavior during (3 - commit) I think is less deterministic and 
> depends on the relative order of traversal of entity properties in the 
> ClassDescriptor. So theoretically there may have been a reverse situation 
> when NULL was saved to the DB, but not-null value remained in the snapshot. 
> In any event it is extremely confusing.
>
> If we take a broader look at this problem, it is a case of redundant mapping 
> (something in the DB layer is mapped multiple times in the object layer). 
> There can be other cases with yet unknown sets of problems (e.g. multiple 
> ObjRelationships over the same DbRelationship; flattened relationships, with 
> a matching set of 1-step relationships; etc).
>
> We only have a single case where redundant mapping is handled correctly and 
> consistently - exposed PK (meaningful or not) . Even if the exposed PK is 
> generated by Cayenne, we have a mechanism to update object property. So this 
> is a case when we do it right, and don't compromise on user choices of 
> mapping scenarios.
>
> In case of exposed FK we have 2 options - (1) just add a Modeler validation 
> to discourage this type of mapping (quick and easy) and (2) actually analyze 
> the above and other possible scenarios when we need to synchronize 
> relationship and attribute and write code to do that. #2 can be done as a 
> post-commit pass over the objects to sync redundant mappings... Just not 
> clear which one of the redundant mappings should be used to sync the others...
>
> Thoughts?

Reply via email to