Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I know this question has been asked numerous times but I couldn't find a suiting answer for me.

I've got two entities in a Spring Roo-application which are in a Many-To-Many-relationship, Release and Component.

First I fetch an instance of an existing Release via

selectedRelease = Release.findReleasesByReleaseNumberEquals(version).getSingleResult();

The method above is a Roo-generated finder which looks like this:

public static TypedQuery<Release> Release.findReleasesByReleaseNummerEquals(String releaseNumber) {
    EntityManager em = Release.entityManager();
    TypedQuery<Release> q = em.createQuery("SELECT o FROM Release AS o WHERE LOWER(o.releaseNumber) LIKE LOWER(:releaseNummer)", Release.class);
    q.setParameter("releaseNumber", releaseNumber);
    return q;
}

Then I create a new instance of Component and try to assign it to the selected Release

Component component = new Component();

Set<Release> releases = new HashSet<Release>();
releases.add(selectedRelease);

component.setReleases(releases);
component.persist();

Upon trying to execute persist() I get the exception:

TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.Release;

Does anyone have advice regarding this problem?

The mappings look like this:

Release.java:

@ManyToMany(cascade = CascadeType.PERSIST, mappedBy = "releases")
private Set<Component> components = new HashSet<Component>();

Component.java

@ManyToMany(cascade=CascadeType.PERSIST)
private Set<Release> releases = new HashSet<Release>();
like image 374
Hedge Avatar asked Mar 03 '12 19:03

Hedge


1 Answers

The message is clear: you are trying to save an object, component, that references another object that hasn't been saved yet, selectedRelease.

The solution seems to be easy: just save (and flush whenever you want the changes be comunicated to the database) the Release objects before saving the Component.

However, JPA allows you to avoid all these sentences with TRANSITIVE PERSISTENCE, that is, the cascade options in the @...ToMany annotations.

Just a warning in case you have a bidirectional relationship, when you have a mappedBy attribute in one of the @...ToMany associations. In this case, you'll need a convenient method to manage the association, that is, to set both sides of the association.

For instance, an addRelease(Release r) in Component that both adds the release to the component's set, and sets the component (actually, the this instance) to the release passed as parameter.

like image 125
jbbarquero Avatar answered Oct 02 '22 19:10

jbbarquero