[2.0-RC2]: Ebean not cascading delete to child object.

1,992 views
Skip to first unread message

Marcos Pereira

unread,
Feb 19, 2012, 10:53:46 PM2/19/12
to play-framework
Hello, 

Not sure if this is related with Ebean or with Play 2.0, but in an one to one bidirectional relationship, with CascadeType.ALL, the delete requests are not being cascaded to the child object. I have created a small problem to show the problem:


My entities are like that:

@Entity
public class Parent extends Model {
  
  @Id
  public Long id;
  
  public String name;
  public Parent(String name) {
    this.name = name;
  }
  
  @OneToOne(mappedBy = "parent", cascade = CascadeType.ALL)
  public Child child;
  
  public static Finder<Long, Parent> find = new Finder<Long, Parent>(
    Long.class, Parent.class
  );
  
  public void setChild(Child child) {
    this.child = child;
    this.child.parent = this;
  }
}

@Entity
public class Child extends Model {

  @OneToOne
  @PrimaryKeyJoinColumn(name = "parent_id")
  public Parent parent;
  
  public String name;
  public Child(String name) {
    this.name = name;
  }
}

And when I call "parent.delete()", I get the following error:

org.h2.jdbc.JdbcSQLException: Referential integrity constraint violation: "FK_CHILD_PARENT_1: PUBLIC.CHILD FOREIGN KEY(PARENT_ID) REFERENCES PUBLIC.PARENT(ID)"; SQL statement: delete from parent where id=? and name=? [23503-158]
     at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
     at org.h2.message.DbException.get(DbException.java:169)
     at org.h2.message.DbException.get(DbException.java:146)
     at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:398)
     at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:415)
     at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:291)
     at org.h2.table.Table.fireConstraints(Table.java:861)
     at org.h2.table.Table.fireAfterRow(Table.java:878)
     at org.h2.command.dml.Delete.update(Delete.java:98)
     at org.h2.command.CommandContainer.update(CommandContainer.java:71)
     at org.h2.command.Command.executeUpdate(Command.java:212)
     at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
     at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
     at com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:203)
     at com.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
     at com.avaje.ebeaninternal.server.persist.dml.DeleteHandler.execute(DeleteHandler.java:80)
     at com.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
     ... 80 more

What I'm doing wrong?

Laurent Bois

unread,
Apr 5, 2012, 10:19:58 AM4/5/12
to play-fr...@googlegroups.com
Hello

I have the same problem with Ebean, in my Unit tests inside a Play 2 application

My 2 object models are :

@Entity

public class Person extends Model {

@OneToOne(cascade=CascadeType.ALL)

public Address address;

}

AND


@Entity

public class Address extends Model {

@OneToOne(cascade=CascadeType.ALL)

public Person person;

}


My object models contain each a "deleteAll()" member method.

In my Unit Test, @Before each test i do :

Person.deleteAll();

Address.deleteAll();

The error message i got on the Person.deleteAll() is :

Referential integrity constraint violation: "FK_ADDRESS_PERSON_1: PUBLIC.ADDRESS FOREIGN KEY(PERSON_ID) REFERENCES PUBLIC.PERSON(ID)"; SQL statement:

[error] delete from person where id=? and last_name=? and first_name=? and pseudonym=? and gender is null and date_of_birth is null and date_of_death is null and address_id is null [23503-158]

[error]     at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)

[error]     at org.h2.message.DbException.get(DbException.java:169)

[error]     at org.h2.message.DbException.get(DbException.java:146)

[error]     at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:398)

[error]     at org.h2.constraint.ConstraintReferential.checkRowRefTable(ConstraintReferential.java:415)

[error]     at org.h2.constraint.ConstraintReferential.checkRow(ConstraintReferential.java:291)

[error]     at org.h2.table.Table.fireConstraints(Table.java:861)

[error]     at org.h2.table.Table.fireAfterRow(Table.java:878)

[error]     at org.h2.command.dml.Delete.update(Delete.java:98)

To avoid this error i should change the "Person" model class :

...

@OneToOne(mappedBy="person",cascade=CascadeType.ALL)

public Address address;

...

But then i have problems in my Unit Test when getting the address via a person :

Person p = Person.findById(1);

assertNotNull(p.address);

The assertNotNull on person.address fails, person.address being null .

Laurent

Angelo K. Huang

unread,
Jul 17, 2012, 3:21:23 PM7/17/12
to play-fr...@googlegroups.com
I have same issue at test cases which has One-to-Many relationship but not child objects are not getting deleted when parent is purged. Anyone has solutions?

Tex

unread,
Jul 19, 2012, 9:56:34 AM7/19/12
to play-fr...@googlegroups.com
Try with orphanRemoval=true...

@OneToOne(mappedBy="person",cascade=CascadeType.ALL, orphanRemoval=true)

I've seen some strange behaviours in ebean, example in @ManyToMany relations with JPA the cascade deletion is done automatically, with ebean I must specify cascading type...

Tex

unread,
Jul 19, 2012, 10:08:57 AM7/19/12
to play-fr...@googlegroups.com
@marcos: when I try to navigate this url:


it shows:

Error
You do not have access to this repository.

I'm logged with my account (giates2000) but I cannot have access credentials...

Anyway, try with orphanRemoval=true...

Marcos Pereira

unread,
Jul 19, 2012, 7:58:58 PM7/19/12
to play-fr...@googlegroups.com
Hi Tex, 

Thanks for the help but the orphanRemoval=true does not worked. I just made the repository public, sorry for that.


--
You received this message because you are subscribed to the Google Groups "play-framework" group.
To view this discussion on the web visit https://groups.google.com/d/msg/play-framework/-/pSQFqIMmHfkJ.

To post to this group, send email to play-fr...@googlegroups.com.
To unsubscribe from this group, send email to play-framewor...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/play-framework?hl=en.

Tex

unread,
Jul 20, 2012, 8:01:51 AM7/20/12
to play-fr...@googlegroups.com
 Hi Marcos,

I've just download your test.

I've tried with 2.1-SNAPSHOT and after minor bugfix it works well !!!

1) When I try to test test (play test) Play 2.1-SNAPSHOT says:

[error] Test models.EbeanTest.should_cascade_delete_to_child_when_deleting_parent failed: No @javax.persistence.Id field found in class [class models.Child]

To avoid the error I add to Child model the @Id annotation, and the finder to test it, so the resulting Child class will be:

package models;
import javax.persistence.Lob;
import javax.persistence.Entity;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import play.db.ebean.Model;
import javax.persistence.*;
@Entity
public class Child extends Model {
  @Id
  public Long id;
  @OneToOne
  @PrimaryKeyJoinColumn(name = "parent_id")
  public Parent parent;
  public String name;
  public Child() {}
  public Child(String name) {
    this.name = name;
  }
  public static Finder<Long, Child> find = new Finder<Long, Child>(Long.class, Child.class);
}

If I modify the EBeanTest savoing models and then check on db counting record, seems that all is ok, after saving Parent if I count how many children record exist it prints 1, after I delete the parent and count how many children record exist it prints 0, so seems it works well or am I missed something ? Below the modified test...

package models;
import java.util.List;
import java.util.ArrayList;
import org.junit.Test;
import org.junit.After;
import org.junit.Before;
import org.junit.Assert;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import play.test.Helpers;
import play.db.ebean.Model;
import play.test.FakeApplication;
public class EbeanTest extends ModelTest<Parent> {
  public List<Parent> fixturesToLoad() {
    List<Parent> list = new ArrayList<Parent>();
    Parent parent = new Parent("Parent");
    Child  child  = new Child("Child");
    parent.setChild(child);
    parent.save();
    System.out.println(Child.find.where().findList().size());
    list.add(parent);
    return list;
  }
  @Test
  public void should_cascade_delete_to_child_when_deleting_parent() {
    Parent parent = Parent.first();
    parent.delete();
    System.out.println(Child.find.where().findList().size());
  }
}

Angelo K. Huang

unread,
Jul 20, 2012, 1:07:32 PM7/20/12
to play-fr...@googlegroups.com
Thanks. It is working now.
Reply all
Reply to author
Forward
0 new messages