digideskio / datanucleus-appengine

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

assigning new value to child field does not delete the old child entity #89

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Because of the way relation is implemented -- parent does not store child
keys (see DatastoreRelationFieldManager.fetchRelationField(). issue 73 is
related) -- the above behavior results in the old entity being returned
when child is accessed later, i.e. updating child does not work.

// ParentPC.java
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class ParentPC {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  public Key identifier;
  @Persistent()
  public ChildPC child;

  public void setChild(ChildPC child) {
    this.child = child;
  }

  public ChildPC getChild() {
    return child;
  }
}

// ChildPC.java
@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class ChildPC implements Serializable, Comparable {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key id;
  private int intField = 0;
  private String stringField;

  public ChildPC() {
  }

  public ChildPC(int intField, String stringField) {
    this.intField = intField;
    this.stringField = stringField;
  }

  public void setIntValue(int intField) {
    this.intField = intField;
  }

  public int getIntValue() {
    return intField;
  }

  public void setStringValue(String stringField) {
    this.stringField = stringField;
  }

  public String getStringValue() {
    return stringField;
  }

  public String toString() {
    return "[" + intField + ", " + stringField + "]";
  }

  public boolean equals(Object obj) {
    if (!(obj instanceof ChildPC)) return false;

    if (intField == ((ChildPC) obj).getIntValue()
        && stringField.equals(((ChildPC) obj).getStringValue()))
      return true;
    else
      return false;
  }

  public int hashCode() {
    return intField ^ stringField.hashCode();
  }

  public int compareTo(Object p) {
    ChildPC sc = (ChildPC) p;
    if (intField < sc.intField) return -1;
    if (intField > sc.intField) return 1;
    return stringField.compareTo(sc.stringField);
  }
}

// QuickTest.java -- this is incomplete, just show the test logic
  public void testParent() {
    ParentPC expectedValue = new ParentPC();
    ParentPC pi = new ParentPC();
    setValues(pi, 1);

    tx.begin();
    pm.makePersistent(pi);
    Object oid = pm.getObjectId(pi);
    tx.commit();

    tx.begin();
    setValues(expectedValue, 1);
    checkValues(oid, expectedValue);

    pi = (ParentPC) pm.getObjectById(oid, true);
    // GAE: This is needed -- setChild(newValue) does not
deletePersistent(oldValue).
    pm.deletePersistent(pi.getChild());
    // Provide new set of values
    setValues(pi, 2);
    tx.commit();

    tx.begin();
    setValues(expectedValue, 2);
    checkValues(oid, expectedValue);
    tx.commit();
  }

  private void setValues(ParentPC obj, int order) {
    if (order == 1) {
      obj.setChild(new ChildPC(1, "Hi "));
    } else {
      obj.setChild(new ChildPC(2, "Low "));
    }
  }

Note the explicit call to deletePersistent() is needed for updating child.

Original issue reported on code.google.com by kerjin2...@gmail.com on 7 Jul 2009 at 1:54

GoogleCodeExporter commented 8 years ago

Original comment by max.r...@gmail.com on 19 Aug 2009 at 1:27

GoogleCodeExporter commented 8 years ago
I ran the same test using the DataNucleus rdbms plugin and got similar behavior 
- the
child is not deleted.  This is sort of confirmed by what is written here:
http://www.datanucleus.org/products/accessplatform_1_1/jdo/orm/cascading.html

The reason this makes more sense for RDBMS than App Engine is that we currently 
query
for the child side of an owned one-to-one via ancestor query, so the child that 
was
"deleted" still hangs around.  Probably not going to fix this for now.  When we 
start
storing child refs on the parent we can revisit.

Original comment by max.r...@gmail.com on 19 Aug 2009 at 4:54

GoogleCodeExporter commented 8 years ago
Or the user could just set that field as dependent field, so as per the JDO 
spec then

Original comment by googleco...@yahoo.co.uk on 21 Sep 2011 at 10:37