Hi there,
I have a circular relation among models, when I try to save the main model
after having populated all the sub-models it throws the following exception:
A javax.persistence.PersistenceException has been caught,
org.hibernate.PropertyValueException: not-null property references a null or
transient value: models.PropertyValue.name
Yet the objects reference is not null, therefore it must be transient. I
believe that JPA saves one side of the model graph before the other and the
object to which PropertyValue.name refers to has not been save yet.
Since it is hard to explain I have attached the simplest version of that
which breaks to see if any of you good Samaritans can give me a hand.
Thanks a million
@Entity
public class MoleculeDatabase extends Model {
@Column(nullable = false)
public String name;
@OneToMany(cascade = CascadeType.ALL)
public List<Molecule> molecules;
@OneToMany(cascade = CascadeType.ALL)
public List<PropertyName> properties;
public MoleculeDatabase() {
super();
this.molecules = new ArrayList<Molecule>();
this.properties = new ArrayList<PropertyName>();
}
}
@Entity
public class Molecule extends Model {
@Column(nullable = false)
public String name;
@ManyToOne(optional = true, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
public MoleculeDatabase database;
@OneToMany(cascade = CascadeType.ALL)
public List<Deployment> deployments;
public Molecule() {
super();
deployments = new ArrayList<Deployment>();
}
}
@Entity
public class Deployment extends Model {
@Column(nullable = false)
public String name;
@ManyToOne(optional = false)
public Molecule molecule;
@OneToMany(cascade = CascadeType.ALL)
public List<PropertyValue> properties;
public Deployment() {
super();
this.properties = new ArrayList<PropertyValue>();
}
}
@Entity
public class PropertyName extends Model {
@Column(nullable = false)
public String name;
@ManyToOne(optional = false)
public MoleculeDatabase database;
}
@Entity
public class PropertyValue extends Model {
@ManyToOne(optional = false)
public PropertyName name;
@Column(nullable = false)
public String value;
@ManyToOne(optional = false)
public Deployment deployment;
}
public class MoleculeDatabaseTest extends UnitTest {
MoleculeDatabase db;
Deployment deployment;
@Before
public void setup(){
db = new MoleculeDatabase();
db.name = "SomeName";
deployment = new Deployment();
deployment.name = "testName_mol12";
Molecule molecule = new Molecule();
molecule.name = "testName_mol12";
molecule.deployments.add(deployment);
deployment.molecule = molecule;
db.molecules.add(molecule);
molecule.database = db;
}
@Test
public void databaseWithPropertiesIsSavedCorrectly(){
PropertyName propertyName = new PropertyName();
propertyName.database = db;
propertyName.name = "COMPND";
db.properties.add(propertyName);
PropertyValue propertyValue = new PropertyValue();
propertyValue.value = "testName_mol12";
propertyValue.name = propertyName;
propertyValue.deployment = deployment;
deployment.properties.add(propertyValue);
assertEquals(db.properties.get(0), deployment.properties.get(0).name);
db.save();
}
}
--
Adrián Perreau de Pinninck Bas, Ph.D
Twitter: @eidrien