I'm getting a TransientObjectException thrown in Hibernate EntityManager's AbstractEntityManagerImpl.joinTransaction(boolean ignoreNotJoining) when committing an object graph with a bidirectional OneToOne mapping.
I have 3 object types involved: Stock -> Financials <-> Ratios, using cascade = ALL to persist them when I persist the top-level Stock object. The error message in the TransientObjectException is:
"object references an unsaved transient instance - save the transient instance before flushing: com.tradegator.model.Ratios.financials -> com.tradegator.model.Financials"
It appears from this message that Hibernate is failing trying to save a transient Financials object referenced by the Ratios object (see my code below). This is confusing to me because although Financials and Ratios are connected by a bidirectional @OneToOne mapping, I have cascade = ALL specified preceding the Financials.getRatios() method. Shouldn't this take care of persisting transient instances of Ratios? Why do I get this error?
Following are my objects (I use JPA annotations for mapping):
Code:
public class Stock {
private List<Financials> financials = new ArrayList<Financials>();
@OneToMany(cascade = CascadeType.ALL)
public List<Financials> getFinancials() {
return this.financials;
}
public void setFinancials(List<Financials> financials) {
this.financials = financials
}
}
public class Financials {
private Ratios ratios;
@OneToOne(cascade = CascadeType.ALL)
public Ratios getRatios() {
return this.ratios;
}
public void setRatios(Ratios ratios) {
this.ratios = ratios;
}
}
public class Ratios {
@OneToOne(mappedBy = "ratios")
public Financials getFinancials() {
return _financials;
}
public void setFinancials(Financials financials) {
this._financials = financials;
}
}
Software versions: Hibernate 3.2.6, Hibernate EntityManager 3.3.1, Hibernate Annotations 3.3.1, Glassfish v2ur2, Java 1.6
Code between sessionFactory.openSession() and session.close():Code:
@Resource
UserTransaction userTxn;
@PersistenceContext
private EntityManager em;
...
userTxn.begin();
Stock s = new Stock(); // Creates Financials and Ratios objects
em.persist(s);
userTxn.commit();
Full stack trace of any exception that occurs:
The stack trace contains a RollbackException. The original TransientObjectException is swallowed by the Hibernate EntityManager code, which btw, should be logged, imho.
Name and version of the database you are using:
MySQL 5.0.45 on Ubuntu Linux
Debug level Hibernate log excerpt:
23:11:25,742 DEBUG CacheSynchronization:40 - transaction before completion callback
23:11:25,748 DEBUG SessionImpl:393 - before transaction completion
23:11:25,753 DEBUG AbstractEntityManagerImpl:515 - automatically flushing session
23:11:25,758 DEBUG SessionImpl:337 - automatically flushing session
23:11:25,764 DEBUG AbstractFlushingEventListener:58 - flushing session
23:11:25,769 DEBUG AbstractFlushingEventListener:111 - processing flush-time cascades
23:11:25,774 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Calculated
23:11:25,780 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Calculated
23:11:25,786 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Estimates
23:11:25,792 DEBUG Cascade:291 - cascade ACTION_PERSIST_ON_FLUSH for collection: com.tradegator.model.Estimates.annualEstimates
23:11:25,798 DEBUG Cascade:306 - done cascade ACTION_PERSIST_ON_FLUSH for collection: com.tradegator.model.Estimates.annualEstimates
23:11:25,804 DEBUG Cascade:291 - cascade ACTION_PERSIST_ON_FLUSH for collection: com.tradegator.model.Estimates.quarterlyEstimates
23:11:25,809 DEBUG Cascade:306 - done cascade ACTION_PERSIST_ON_FLUSH for collection: com.tradegator.model.Estimates.quarterlyEstimates
23:11:25,815 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Estimates
23:11:25,821 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Stock
23:11:25,827 DEBUG Cascade:291 - cascade ACTION_PERSIST_ON_FLUSH for collection: com.tradegator.model.Stock.annualFinancials
23:11:25,832 DEBUG CascadingAction:321 - cascading to persistOnFlush: com.tradegator.model.Financials
23:11:25,839 DEBUG AbstractSaveEventListener:514 - transient instance of: com.tradegator.model.Financials
23:11:25,845 DEBUG DefaultPersistEventListener:124 - saving transient instance
23:11:25,852 DEBUG Isolater:96 - surrounding JTA transaction suspended [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:25,860 DEBUG SQL:132 - select GEN_VALUE from ID_GEN where GEN_KEY = 'TG_SEQ' for update
23:11:25,870 DEBUG Isolater:150 - surrounding JTA transaction resumed [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:25,877 DEBUG MultipleHiLoPerTableGenerator:194 - new hi value: 20
23:11:25,884 DEBUG AbstractSaveEventListener:112 - generated identifier: 400, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
23:11:25,891 DEBUG AbstractSaveEventListener:153 - saving [com.tradegator.model.Financials#400]
23:11:25,898 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Financials
23:11:25,905 DEBUG CascadingAction:321 - cascading to persistOnFlush: com.tradegator.model.BalanceSheet
23:11:25,913 DEBUG AbstractSaveEventListener:514 - transient instance of: com.tradegator.model.BalanceSheet
23:11:25,920 DEBUG DefaultPersistEventListener:124 - saving transient instance
23:11:25,928 DEBUG Isolater:96 - surrounding JTA transaction suspended [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:25,936 DEBUG SQL:132 - select GEN_VALUE from ID_GEN where GEN_KEY = 'TG_SEQ' for update
23:11:25,947 DEBUG Isolater:150 - surrounding JTA transaction resumed [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:25,955 DEBUG MultipleHiLoPerTableGenerator:194 - new hi value: 21
23:11:25,962 DEBUG AbstractSaveEventListener:112 - generated identifier: 420, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
23:11:25,970 DEBUG AbstractSaveEventListener:153 - saving [com.tradegator.model.BalanceSheet#420]
23:11:25,977 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.BalanceSheet
23:11:25,985 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.BalanceSheet
23:11:25,993 DEBUG Versioning:56 - Seeding: 0
23:11:26,002 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.BalanceSheet
23:11:26,010 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.BalanceSheet
23:11:26,017 DEBUG CascadingAction:321 - cascading to persistOnFlush: com.tradegator.model.CashFlow
23:11:26,025 DEBUG AbstractSaveEventListener:514 - transient instance of: com.tradegator.model.CashFlow
23:11:26,033 DEBUG DefaultPersistEventListener:124 - saving transient instance
23:11:26,040 DEBUG Isolater:96 - surrounding JTA transaction suspended [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,049 DEBUG SQL:132 - select GEN_VALUE from ID_GEN where GEN_KEY = 'TG_SEQ' for update
23:11:26,061 DEBUG Isolater:150 - surrounding JTA transaction resumed [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,069 DEBUG MultipleHiLoPerTableGenerator:194 - new hi value: 22
23:11:26,076 DEBUG AbstractSaveEventListener:112 - generated identifier: 440, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
23:11:26,084 DEBUG AbstractSaveEventListener:153 - saving [com.tradegator.model.CashFlow#440]
23:11:26,091 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.CashFlow
23:11:26,099 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.CashFlow
23:11:26,107 DEBUG Versioning:56 - Seeding: 0
23:11:26,115 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.CashFlow
23:11:26,123 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.CashFlow
23:11:26,131 DEBUG CascadingAction:321 - cascading to persistOnFlush: com.tradegator.model.FiscalPeriod
23:11:26,138 DEBUG AbstractSaveEventListener:514 - transient instance of: com.tradegator.model.FiscalPeriod
23:11:26,145 DEBUG DefaultPersistEventListener:124 - saving transient instance
23:11:26,153 DEBUG Isolater:96 - surrounding JTA transaction suspended [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,161 DEBUG SQL:132 - select GEN_VALUE from ID_GEN where GEN_KEY = 'TG_SEQ' for update
23:11:26,172 DEBUG Isolater:150 - surrounding JTA transaction resumed [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,180 DEBUG MultipleHiLoPerTableGenerator:194 - new hi value: 23
23:11:26,188 DEBUG AbstractSaveEventListener:112 - generated identifier: 460, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
23:11:26,196 DEBUG AbstractSaveEventListener:153 - saving [com.tradegator.model.FiscalPeriod#460]
23:11:26,203 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.FiscalPeriod
23:11:26,211 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.FiscalPeriod
23:11:26,219 DEBUG Versioning:56 - Seeding: 0
23:11:26,227 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.FiscalPeriod
23:11:26,235 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.FiscalPeriod
23:11:26,243 DEBUG CascadingAction:321 - cascading to persistOnFlush: com.tradegator.model.IncomeStatement
23:11:26,250 DEBUG AbstractSaveEventListener:514 - transient instance of: com.tradegator.model.IncomeStatement
23:11:26,258 DEBUG DefaultPersistEventListener:124 - saving transient instance
23:11:26,266 DEBUG Isolater:96 - surrounding JTA transaction suspended [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,275 DEBUG SQL:132 - select GEN_VALUE from ID_GEN where GEN_KEY = 'TG_SEQ' for update
23:11:26,285 DEBUG Isolater:150 - surrounding JTA transaction resumed [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,294 DEBUG MultipleHiLoPerTableGenerator:194 - new hi value: 24
23:11:26,302 DEBUG AbstractSaveEventListener:112 - generated identifier: 480, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
23:11:26,310 DEBUG AbstractSaveEventListener:153 - saving [com.tradegator.model.IncomeStatement#480]
23:11:26,317 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.IncomeStatement
23:11:26,325 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.IncomeStatement
23:11:26,333 DEBUG Versioning:56 - Seeding: 0
23:11:26,342 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.IncomeStatement
23:11:26,350 DEBUG Cascade:150 - done processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.IncomeStatement
23:11:26,358 DEBUG CascadingAction:321 - cascading to persistOnFlush: com.tradegator.model.Ratios
23:11:26,366 DEBUG AbstractSaveEventListener:514 - transient instance of: com.tradegator.model.Ratios
23:11:26,373 DEBUG DefaultPersistEventListener:124 - saving transient instance
23:11:26,381 DEBUG Isolater:96 - surrounding JTA transaction suspended [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,389 DEBUG SQL:132 - select GEN_VALUE from ID_GEN where GEN_KEY = 'TG_SEQ' for update
23:11:26,400 DEBUG Isolater:150 - surrounding JTA transaction resumed [J2EETransaction: txId=305 nonXAResource=59 jtsTx=null localTxStatus=0 syncs=[com.sun.ejb.containers.ContainerSynchronization@773b3d, org.hibernate.transaction.CacheSynchronization, org.hibernate.ejb.AbstractEntityManagerImpl$1@1d22b43, com.sun.enterprise.resource.PoolManagerImpl$SynchronizationListener@11665ac]]
23:11:26,409 DEBUG MultipleHiLoPerTableGenerator:194 - new hi value: 25
23:11:26,416 DEBUG AbstractSaveEventListener:112 - generated identifier: 500, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
23:11:26,424 DEBUG AbstractSaveEventListener:153 - saving [com.tradegator.model.Ratios#500]
23:11:26,431 DEBUG Cascade:115 - processing cascade ACTION_PERSIST_ON_FLUSH for: com.tradegator.model.Ratios
23:11:26,439 DEBUG VersionValue:44 - version unsaved-value strategy UNDEFINED
23:11:26,449 DEBUG AbstractEntityManagerImpl:418 - mark transaction for rollback
23:11:26,456 DEBUG CacheSynchronization:82 - transaction after completion callback, status: 4
23:11:26,461 DEBUG SessionImpl:422 - after transaction completion
23:11:26,467 DEBUG SessionImpl:273 - closing session