Hello,
For some reason, I am unable to update an object that is already
persisted. Here's how it goes:
I have a Shape object that includes an Attachment. This is already
saved in the database. I update the Shape by replacing its Attachment
object with a new one that contains a Note object:
manager.getTransaction().begin();
Shape loadedBase = manager.find( Shape.class, 18 );
// Create new attachment
Attachment newAttach = new Attachment();
newAttach.setValue( "attachment 2" );
Note note = new Note();
note.setText( "note text" );
note.setParent( newAttach );
newAttach.setNote( note );
newAttach.setParent( loadedBase );
loadedBase.setAttachment( newAttach );
manager.getTransaction().commit();
Upon commiting this transaction, I see the following statements:
INSERT INTO NOTE (NOTE_TEXT) VALUES (?) [params=(String) note text]
INSERT INTO ATTACH (SHAPE_ID, VALUE) VALUES (?, ?) [params=(int) 12,
(String) attachment 2]
CALL IDENTITY()
DELETE FROM ATTACH WHERE ATTACH_ID = ? [params=(int) 44]
UPDATE NOTE SET PARENT_ID = ? WHERE NOTE_ID = ? [params=(int) 45, (int) 0]
The first statement in the list throws an exception as Note must
provide a parent:
Attempt to insert null into a non-nullable column: column: PARENT_ID
table: NOTE in statement [INSERT INTO NOTE (NOTE_TEXT) VALUES (?)]
{prepstmnt 11544872 INSERT INTO NOTE (NOTE_TEXT) VALUES (?)
[params=(String) note text]} [code=-10, state=23000]
What am I doing wrong?
I am able to get the transaction to commit properly by either
- setting PROPERTY access on the Note object;
- detaching the Shape object before updating it and calling merge();
- starting my transaction once my new Attachment object is created and
Note object is set;
- stepping inside the code using Eclipse.
In all cases, the Attachment object is inserted first and then the
Note object is inserted with a reference to the Attachment.
Thanks in advance!
Christian
-----
@Entity
@Table(name="SHAPE")
public class Shape
{
@Column(name="shape_id")
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
@OneToOne( mappedBy="parent", cascade=CascadeType.ALL,
fetch=FetchType.EAGER )
@Dependent
private Attachment attachment;
// Getters and setters are trivial
}
@Entity
@Table( name="attach" )
public class Attachment
{
@Id
@GeneratedValue( strategy=GenerationType.IDENTITY )
@Column( name="attach_id" )
private int id;
@OneToOne( cascade=CascadeType.ALL, fetch=FetchType.LAZY )
@Column( name="shape_id" )
private Shape parent;
private String value;
@OneToOne( mappedBy="parent", cascade=CascadeType.ALL )
private Note note;
// Getters and setters are trivial
}
@Entity
@Table( name="note" )
public class Note
{
@Id
@GeneratedValue( strategy=GenerationType.IDENTITY )
@Column( name="note_id" )
private int id;
@OneToOne( optional=false )
@Column( name="parent_id" )
private Attachment parent;
@Column( name="note_text", length=20 )
private String text;
// Getters and setters are trivial
}