In EJB3, there has always been a problem on one to manys and this type of code...
newNode = mgr.merge(newNode);
script.addNode(newNode); //where this also calls newNode.setScript(this);
The problem is when the constraint on newNode.getScript is nullable=false. When this happens, the code above fails and mgr.merge throws an Exception....then you try moving script.addNode(newNode) above mgr.merge() which fails in later code for other reasons. Below is my code snippet of how we solved the problem(I hope someone finds this useful). I hope even better someone has a better solution. I do believe mgr.merge should NOT be checking constraints ...I should be able to screw with the model all I want until the transaction is committed and the transaction.commit should validate all the constraints(alas, hibernate does not do it this way :( ).
code.....
Code:
//BIG BIG NOTE: We wanted to have this code
//newNode = mgr.merge(newNode);
//script.addNode(newNode);
//
//Unfortunately, then you get a ConstraintViolationException on mgr.merge because
//you are merging a node without a script and script is required!!!!
//Then we move to this code....
//script.addNode(newNode);
//newNode =mgr.merge(newNode);
//
//This code then fails later on when script.getImmutableNodes is called as
//all nodes in the List MUST have an id and adding the newNode before the merge
//causes a node without an id to be added to the script. Only the newNode
//returned from mgr.merge has an id. Realize the newNode returned from mgr.merge
//IS A DIFFERENT instance than the newNode passed into mgr.merge so basically
//the script has the wrong instance of newNode with this code and an exception
//happens later when the List of entities is passed through the entityConverter
//The other problem is you should not be giving transient instances of Node to
//the script as you will have merge problems later sometimes.
public void save() {
Node temp = newNode;
script.addNode(temp);
newNode = mgr.merge(temp);
script.removeNode(temp);
script.addNode(newNode);
}
ps. I am using the seam entityConverter which requires all Node's have an id. Also, that could be a mute point as I would not want my script to end up with a transient instance of Node anyways. I want my script to have the Node that was merged, not the pre-merge node.
I hope this helps someone else as it has burned me for years!!!!! and I finally figured out this hack work around until someone has something better.
Dean