2017-01-02 68 views
0

我有以下兩個類。 「類型」類具有「內容」類的對象。 我想通過使用hibernate.save()方法保存類'Type'的所有引用對象。我在類「內容」中將級聯類型指定爲ALL。Hibernate無法使用級聯保存子對象全部

以下是我面對的錯誤: 對象引用未保存的瞬態實例 - 在刷新之前保存瞬態實例。

有人可以幫我找出問題所在嗎?

public class Type { 
    @OneToOne 
    @JoinColumn(name = "content_id") 
    private Content content; 
    } 

    public class Content { 
     @OneToOne(mappedBy = "content", cascade = CascadeType.ALL) 
     private Type type; 
    } 

    public class Test { 
     public void createType() { 
      Type type = new Type(); 
      Content content = someMethodToGetContent(); 
      type.setContent(content); 
      save(type); 
     } 

     public void save(Object domainObj) { 
      getEntityManager().persist(domainObj); 
      getEntityManager().flush(); 
     } 
    } 

堆棧跟蹤:

產生的原因:org.hibernate.TransientObjectException: - 對象引用 未保存的瞬態的實例之前 沖洗保存瞬態的實例:。內容 - >。內容在 org.hibernate.engine.CascadingAction $ 9.noCascade(CascadingAction.java:387) at org.hibernate.engine.Cascade.cascade(Cascade.java:172)at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush( AbstractFlushingEventListener.java:154) 在 org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145) 在 org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88) 在 org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) 在org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)在 org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl .java:795) ... 27更多 org.springframework.transaction.TransactionSystemException:無法提供 提交JPA事務;嵌套的異常是 javax.persistence.RollbackException:Transacti上標記爲 rollbackOnly在 org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:526) 在 org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit (AbstractPlatformTransactionManager.java:761) 在 org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:730) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:504) 在 org.springframework.transaction.interceptor.Tran sactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:292) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java: 179) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 在com.sun.proxy $ Proxy29.persist(來源不明)產生的原因:。 javax.persistence.RollbackException:交易標記爲 rollbackOnly在 org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:73)at org.springframework.orm.jpa.JpaTransactionManage r.doCommit(JpaTransactionManager.java:517) ...12更多

+0

代碼試圖保存在哪裏?它節省了什麼?什麼是異常的**完整**堆棧跟蹤? –

+0

你的班上有沒有一個瞬態變量? – msagala25

+0

@JBNizet:增加了代碼 – minion

回答

1

休眠無法保存使用級聯子對象的所有

之所以這不起作用與你想persit實體的方式做。

  • 讓我們看看下面的代碼是這樣做的:

    Type type = new Type(); 
    Content content = someMethodToGetContent(); 
    type.setContent(content); 
    save(type); 
    

您可以通過調用save(type)並期待content告訴你要保存type持久性提供者也應該被保存到數據庫。但在實體Type中,OneToOne註釋不包含PERSIST級聯選項。所以,你必須告訴持久性提供給pesist的Content實例時的Type一個實例是通過改變你的OneToOne註釋堅持如下:

@OneToOne(cascade=CascadeType.PERSIST) // modified 
@JoinColumn(name = "content_id") 
private Content content; 

因爲你定義的實體有雙向關係,你應正確連線如下:

Type type = new Type(); 
Content content = someMethodToGetContent(); 
content.setType(type);      // modified 
type.setContent(content); 
save(type); 
+0

非常感謝你指出我錯過了什麼。我在「類型」類中添加了級聯選項,並且對象被保留。萬分感謝! – minion

+0

我還有一個問題。可以說上面的對象'Type'與許多對象'A','B','C'有1-1關係。我想確保每當'類型'被持續時'A','B'和'C'也是如此。但不是相反,即當我堅持'A'我不希望'類型'被堅持。 如果我只在'Type'類中添加CASCADE選項,而不是在'A','B','C'類中添加,則應該實現此功能。我對麼? – minion

+0

是的。如果'A'在它的1-1關係中沒有指定級聯類型'PERSIST',那麼持久性提供者將不會試圖持久化所引用的實體。但是你應該知道一些事情:如果與'A'相對應的表持有一個與Type相對應的表的外鍵,並且這個列標記爲'NOT NULL',那麼你會得到數據庫約束違規錯誤,因爲父項實體不會被持久化。 – ujulu

1

請更改您的createType()如下。

public void createType() { 
Type type = new Type(); 
Content content = someMethodToGetContent(); 
content.setType(); 
type.setContent(content); 
save(type); 
} 
+0

Sreenath:謝謝你的答案。正如@ujulu指出的,我在'Type'類中添加了級聯選項,並且在你們都提到並改變了createType方法的情況下持久化了Type對象,並且它工作正常。 – minion