TransientObjectException:对象引用了一个未保存的临时实例 - 在刷新之前保存临时实例。

5

我知道这个问题已经被问了很多次,但是我找不到一个适合我的答案。

我有两个实体在Spring Roo应用程序中,它们处于多对多关系中,Release和Component。

首先,我通过

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

上述方法是由Roo生成的查找器,其代码如下:
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;
}

然后,我创建了一个新的组件实例,并尝试将其分配给所选的发布版本。
Component component = new Component();

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

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

当我尝试执行persist()时,出现了以下异常:

TransientObjectException:对象引用未保存的瞬态实例 - 请在刷新之前保存瞬态实例:com.Release;

有没有人能提供关于这个问题的建议?

映射如下:

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>();

你能够发布你的 ReleaseComponent 的映射吗? - ManuPK
我通过在执行setReleases()之前执行persist()来解决了这个问题。 - Hedge
1个回答

9
信息很明确:您正在尝试保存一个引用另一个未保存的对象selectedRelease的对象或组件。
解决方案似乎很简单:在保存Component之前,只需保存(并在需要将更改通知到数据库时刷新)Release对象即可。
然而,JPA允许您通过级联选项在@...ToMany注释中使用传递性持久性来避免所有这些语句。
但是,请注意,如果您有双向关系,在@...ToMany关联中的其中一个具有mappedBy属性的情况下,您将需要一个方便的方法来管理关联,即设置关联的两个方面。
例如,在Component中添加一个addRelease(Release r)方法,该方法既将发布添加到组件的集合中,又将组件(实际上是传递的this实例)设置为传递的发布。

1
感谢您的建议。我在映射的两端都添加了cascade=CascadeType.PERSIST,但它仍然无法正常工作。这可能是因为我没有管理关联的方法吗?您能给个例子吗? - Hedge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接