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

2

22

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();
    }
}   
Thermotensile answered 20/11, 2012 at 16:51 Comment(2)
S
33

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.

Singlehandedly answered 28/11, 2012 at 9:15 Comment(2)
i didn't get that, is there any tutorial available or you can explain further. How Note is transient ?Huckaback
NoteItem noteItem = ; noteItem.Note = new Note(); session.Save(noteItem);Singlehandedly
J
0

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

Jospeh answered 26/7, 2020 at 13:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.