Not-null property references a null or transient value


Context:

Trying to run an application (using spring & hibernate) that has a parent (one) and child (many) relationship. When trying to add a parent, children maybe added at runtime and once submit is pressed both the parent and the respective children are saved.

To add the children at run time isFormChangeRequestonFormChangemethods, provided by spring, are used. And when submitting the parent form, hibernate helps to save the children automatically when the parent is saved.

The following is an excerpt of what the mapping looks like…

<set name="children" inverse="true" cascade="all-delete-orphan">
    <key column="PARENT_ID" not-null="true"/>
    <one-to-many/>
</set>

Problem:

After submit is pressed, the following creeps up….

org.springframework.dao.PropertyValueException: not-null property references a null or transient value:...

It seems like one of the child properties is missing, but a simple System.out.print shows that the property being complained about is NOT null !

Solution:

The problem was to do with hibernate not “automatically” being able to store the child to the db (although the information was saved in memory)….. because the relationship between the parent and the child had not properly been set up. So although the hibernate mapping was fine, it was not being applied because the parent-child relationship was faulty.

[Please note, that there could be several solutions to this problem,  rather than try and list all of them here… I thought it best to try and explain the CONCEPT behind the solution.]

Examples:

So like I said above, the problem is to do with a faulty parent-child relationship… it may not necessarily be to do with the hibernate mapping file. It could be many other things like the addChild() method not being written properly in the FooParent.java,  or perhaps missing the part which adds the newly created child to the parent… so although the child is being created it is not being properly added to the parent and hence being confronted with a message that indicates a transient (meaning temporary) value or object that has been created but not properly saved.

So let me repeat again, in order to solve this problem, you need to check all the parent-child code (especially the add & edit controllers) and ensure that after the child is created it is being added to the parent and then being saved.

For example, instead of….

child.setParent(parent);
getSession().save(child);

also add, one other line …

parent.getChildren().add(child);

child.setParent(parent);
getSession().save(child);

JPA EntityManager: Why use persist() over merge()?


http://stackoverflow.com/questions/1069992/jpa-entitymanager-why-use-persist-over-merge

Either way will add an entity to a PersistenceContext, the difference is in what you do with the entity afterwards.

Persist takes an entity instance, adds it to the context and makes that instance managed (ie future updates to the entity will be tracked)

Merge creates a new instance of your entity, copies the state from the supplied entity, and makes the new copy managed. The instance you pass in will not be managed (any changes you make will not be part of the transaction – unless you call merge again).

Maybe a code example will help.

MyEntity e = new MyEntity();

// scenario 1
// tran starts
em.persist(e);
e.setSomeField(someValue);
// tran ends, and the row for someField is updated in the database

// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue);
// tran ends but the row for someField is not updated in the database (you made the changes *after* merging

// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue);
// tran ends and the row for someField is updated (the changes were made to e2, not e)

Scenario 1 and 3 are roughly equivalent, but there are some situations where you’d want to use Scenario 2.