Comment 0 for bug 612137

Revision history for this message
mattanja (mattanja) wrote :

I ran into a problem while trying to load a fixtures file when at first the following exception occured:

RuntimeException occured : Cannot load fixture initial-data.yml: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: models.OrganizationUnit.parent -> models.OrganizationUnit

The affected property was:
@Entity
public class OrganizationUnit extends Model {
[...]
 @ManyToOne(targetEntity = models.OrganizationUnit.class)
 public OrganizationUnit parent;
[...]
}

Next I changed the annotation to include cascading:
 @ManyToOne(targetEntity = models.OrganizationUnit.class, cascade = CascadeType.ALL)
 public OrganizationUnit parent;

The result was that I got an empty new object in the database that is not included in the YAML-data.
initial-data.yml contains:
OrganizationUnit(orgRoot):
    lft: 0
    rgt: 3
    name: root
    externalId: root
    shortName: 1

OrganizationUnit(orgChild):
    lft: 1
    rgt: 2
    name: child
    externalId: child
    shortName: 2
    parent: orgRoot

After importing those objects the database contained:
 id externalId level lft name rgt shortName parent_id
2 NULL 0 0 NULL 0 NULL NULL
3 root 0 0 root 3 1 2
4 child 0 1 child 2 2 3

I did some debugging and as a workaround I created the setter
 public void setParent(OrganizationUnit parent) {
  if (parent == null) {
   this.parent = null;
  } else if (parent.externalId == null) {
   this.parent = null;
  } else {
   this.parent = parent;
  }
 }
that avoids the creation of the empty object.

The empty object gets created in play.data.binding.map.BeanWrapper.java in Line 64
but I did not figure out why.