ludoch / datanucleus-appengine

Automatically exported from code.google.com/p/datanucleus-appengine
0 stars 0 forks source link

Can't delete an unowned entity when schema has been migrated. #300

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
I originally had a unilateral unowned @OneToMany where the children knew 
nothing about the parent. Later I added the 2 way relationship using the 
@OneToMany(mappedBy="parentEntity"). The problem arises when I try to delete 
the entities that do not have a parent set. It seems that I should still be 
able to remove the Table entity without having their establishment set.

// This is the exception I am receiving
Caused by: org.datanucleus.exceptions.NucleusException: Object Table(511) has 
unowned property com.test.server.domain.Table.establishment but no 
corresponding property establishment_id on its datastore entity.
    at com.google.appengine.datanucleus.FetchFieldManager.lookupOneToOneChild(FetchFieldManager.java:595)
    at com.google.appengine.datanucleus.FetchFieldManager.fetchRelationField(FetchFieldManager.java:541)
    at com.google.appengine.datanucleus.FetchFieldManager.fetchObjectField(FetchFieldManager.java:405)
    at org.datanucleus.state.AbstractStateManager.replacingObjectField(AbstractStateManager.java:2353)
....

// Parent Class
@Entity
public class Establishment extends DatastoreObject {

    @OneToMany(fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, mappedBy = "establishment")
    private List<Table> tables = new ArrayList<Table>();
}

// Child Class
@Entity
public class Table extends DatastoreObject {

        // This was added after many children had been created. All children created before this I cannot delete.
    @ManyToOne(fetch = FetchType.LAZY, optional = true, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    private Establishment establishment; 
}

It appears to be getting caught in the else clause.

        if (value instanceof Key) {
          DatastoreServiceConfig config = getStoreManager().getDefaultDatastoreServiceConfigForReads();
          DatastoreService datastoreService = DatastoreServiceFactoryInternal.getDatastoreService(config);
          try {
            Entity childEntity = datastoreService.get((Key)value);
            return EntityUtils.entityToPojo(childEntity, childCmd, clr, ec, false, ec.getFetchPlan());
          } catch (EntityNotFoundException enfe) {
            // TODO: Should this throw a data integrity exception? It seems to for oneToMany.
            NucleusLogger.PERSISTENCE.error("Field " + mmd.getFullFieldName() + " of " + getObjectProvider().getInternalObjectId() +
                " was pointing to object with key " + value + " but this doesn't exist!");
            return null;
          }
        }
      } else if (MetaDataUtils.isOwnedRelation(mmd)) {
          // Not yet got the property in the parent, so this entity has not yet been migrated to latest storage version
          NucleusLogger.PERSISTENCE.info("Persistable object at field " + mmd.getFullFieldName() + " of " + op +
          " not yet migrated to latest storage version, so reading the object via its parent key");
      } else {
        // Unowned relation but we don't have the property? That's bad data.
        throw new NucleusException("Object " + datastoreEntity.getKey() + " has unowned property " + mmd.getFullFieldName() +
          " but no corresponding property " + propName + " on its datastore entity.");
      }
    }

GAE 1.7.0
// Datanucleus version
datanucleus-appengine-2.1.1-SNAPSHOT.jar

Original issue reported on code.google.com by chris.hi...@gmail.com on 4 Sep 2012 at 8:33

GoogleCodeExporter commented 8 years ago
SVN turnk likely works, but then you'd have to confirm that yourself since no 
test was provided.

Original comment by googleco...@yahoo.co.uk on 27 Sep 2012 at 11:08