TransientObjectException - object references an unsaved transient instance - save the transient instance before flushing

StackOverflow https://stackoverflow.com/questions/13478055

Question

I've come across a few good possible answers to my questions, but this is regarding an upgrade from Hibernate 3.4.0GA to Hibernate 4.1.8. So this used to work under the previous version and I've searched high and low for why its breaking in this new version.

I get a

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.test.server.domain.model.NoteItem.note -> com.test.server.domain.model.Note

Any help would be great.

Here are my classes.

@MappedSuperclass
public abstract class EntityBase implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    protected Long id;

    @Version
    @Column(name = "VERSION")
    protected Long version; 

    public Long getId() {
        return id;
    }

    public Long getVersion() {
        return version;
    }

    protected static final EntityManager entityManager() {
        return EntityManagerUtil.getEntityManager();
    }
}

@Entity
@Table(name = "WORK_BOOK")
public class WorkBook extends EntityBase {
    private static final long serialVersionUID = 1L;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "NOTE_ID")
    private Note note;

    public WorkBook() {
        super();
    }

    public Note getNote() {
        return note;
    }

    public void setNote(Note note) {
        this.note = note;
    }

    public WorkBook persist() {
        EntityManager em = entityManager();
        EntityTransaction tx = em.getTransaction();

        if (tx.isActive()) {
            return em.merge(this);
        } else {
            tx.begin();
            WorkBook saved = em.merge(this);
            tx.commit();
            return saved;
        }
    }
}

@Entity
@Table(name = "NOTE")
public class Note extends EntityBase {
    private static final long serialVersionUID = 1L;

    @OneToOne(mappedBy = "note")
    private WorkBook workBook;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "note")
    private List<NoteItem> notes = new ArrayList<NoteItem>();

    public WorkBook getWorkBook() {
        return workBook;
    }

    public List<NoteItem> getNotes() {
        return notes;
    }

    public void setWorkBook(WorkBook workBook) {
        this.workBook = workBook;
    }

    public void setNotes(List<NoteItem> notes) {
        if (notes != null) {
            for (NoteItem ni : notes) {
                ni.setNote(this);               
            }
        }

        this.notes = notes;
    }
}   

@Entity
@Table(name = "NOTE_ITEM")
public class NoteItem extends EntityBase {
    private static final long serialVersionUID = 1L;

    @Column(name = "NOTE_NAME")
    private String noteName;

    @Column(name = "NOTE_TEXT")
    private String noteText;

    @Column(name = "NOTE_DATE")
    private Date noteDate;

    @Column(name = "NOTE_CREATOR")
    private String noteCreator;

    @Column(name = "NOTE_CREATOR_ID")
    private Integer noteCreatorId;

    @ManyToOne
    @JoinColumn(name = "NOTE_ID", updatable = true)
    private Note note;

    public String getNoteName() {
        return noteName;
    }

    public void setNoteName(String noteName) {
        this.noteName = noteName;
    }

    public String getNoteText() {
        return noteText;
    }

    public void setNoteText(String noteText) {
        this.noteText = noteText;
    }

    public Date getNoteDate() {
        return noteDate;
    }

    public void setNoteDate(Date noteDate) {
        this.noteDate = noteDate;
    }

    public String getNoteCreator() {
        return noteCreator;
    }

    public void setNoteCreator(String noteCreator) {
        this.noteCreator = noteCreator;
    }

    public Integer getNoteCreatorId() {
        return noteCreatorId;
    }

    public void setNoteCreatorId(Integer noteCreatorId) {
        this.noteCreatorId = noteCreatorId;
    }

    public Note getNote() {
        return note;
    }

    public void setNote(Note note) {
        this.note = note;
    }

    public NoteItem create() {
        return new NoteItem();
    }
}   
Was it helpful?

Solution

NoteItem references a transient (not yet saved) instance of Note which has to be saved before. So specify "Cascade.all" on property note or call saveorupdate on Note first.

OTHER TIPS

I was facing the same error for all PUT HTTP transactions, after introducing optimistic locking (@Version)

At the time of updating an entity it is mandatory to send id and version of that entity. If any of the entity fields are related to other entities then for that field also we should provide id and version values, without that the JPA try to persist that related entity first

Example: we have two entities --> Vehicle(id,Car,version) ; Car(id, version, brand) to update/persist Vehicle entity make sure the Car field in vehicle entity has id and version fields provided

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top