# hibernate - TransientObjectException



## y0dA (4. Feb 2008)

Hi!
Ich habe 2 Tabellen welche 1:n zueinander stehen.

Receiver Tabelle  1<-----------------------n Track Tabelle

Mapping:
*Receiver*

```
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.pcd.wam.gegenstandsbereich.streetDetection.persistence.model">
  <class name="org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.valueObject.Receiver"
  		table="RECEIVER">   		  
		
		<id name="id" type="integer" column="RE_ID">
		<generator class="increment" />
		</id>		
		<property name="globalID" type="string" column="RE_GLOBAL_ID" />
		<property name="description" type="string" column="RE_DESC" />
	</class>
</hibernate-mapping>
```

*Track*

```
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.pcd.wam.gegenstandsbereich.streetDetection.persistence.model">
  <class name="org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.valueObject.Track"
  		table="TRACK">  		
  				
		<id name="id" type="integer" column="T_ID">
		<generator class="increment" />
		</id>		
		<many-to-one name="receiver" class="org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.valueObject.Receiver"
				column="T_RE_ID" lazy="false"/>		
		<property name="end" type="timestamp" column="T_END" />
		<property name="cmt" type="string" column="T_GPS_CMT" />
		<property name="start" type="timestamp" column="T_START" />
		<property name="desc" type="string" column="T_USER_DESC" />  		
  </class>  
</hibernate-mapping>
```


Exceptionstelle:

```
public void storeTracks(final List<Track> tList, final Receiver receiver) {
		TrackDAO trackDAO = new TrackDAO();
		TrackPointDAO trackPointDAO = new TrackPointDAO();
		try {
			HibernateUtil.getCurrentSession().beginTransaction();			
			trackDAO.setSession(HibernateUtil.getCurrentSession());
			trackPointDAO.setSession(HibernateUtil.getCurrentSession());
			for (Track track : tList) {
				trackDAO.makePersistent(track);
				for (TrackPoint point : track.getTrackPointList()) {
					trackPointDAO.makePersistent(point);	
				}
			}					  
			HibernateUtil.getCurrentSession().getTransaction().commit();	
		} catch (Exception e) {
			e.printStackTrace();
			if (HibernateUtil.getCurrentSession().getTransaction() != null) {
				HibernateUtil.getCurrentSession().getTransaction().rollback();
				TrackControllerModel.LOGGER.fatal(
						"class: TrackControllerModel method: storeTracks, exception occurred while"
						+ " store tracks: ", e);
			}
		} finally {
			trackDAO = null;
			trackPointDAO = null;
		}
	}
```

Nun ist der Sachverhalt so, dass ich einen Track in die Datenbank schreiben möchte und ich dann folgende Exception bekomme:

```
04.02.2008 13:43:48 at.pcd.wam.technologie.utility.hibernate.HibernateUtil getSessionFactory
INFO: initialize hibernate session factory, class: HibernateUtil method: getSessionFactory
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.valueObject.Receiver
	at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:219)
	at org.hibernate.type.EntityType.getIdentifier(EntityType.java:397)
	at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:242)
	at org.hibernate.type.TypeFactory.findDirty(TypeFactory.java:597)
	at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:3123)
	at org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:479)
	at org.hibernate.event.def.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:204)
	at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:127)
	at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:196)
	at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:76)
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:106)
	at org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.TrackControllerModel.storeTracks(TrackControllerModel.java:394)
	at org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.TrackControllerModel.storeTracks(TrackControllerModel.java:337)
	at org.pcd.wam.gegenstandsbereich.streetDetection.domain.model.locating.TrackControllerModel.storeTracks(TrackControllerModel.java:352)
	at org.pcd.wam.test.TestTrackControllerModel.main(TestTrackControllerModel.java:44)
```

Aber warum das Receiver Objekt transient sein soll verstehe ich nicht so ganz, da ich es vor dem Insert des Tracks aus der DB hole und dann dem Track umhänge.
Was mache ich hierbei falsch bzw. wie kann ich den Track ein persistentes Receiver Objekt umhängen?


----------



## SlaterB (4. Feb 2008)

woher weißt du denn, dass Receiver ein persistentes Objekt ist?
du hast hier nichts davon gepostet,

teste mal, ob receiver transient ist oder nicht:
session.contains(receiver)


und wirf diese unsäglich oft wiederholten HibernateUtil.getCurrentSession()-Aufrufe raus,

einmal
Session session = HibernateUtil.getCurrentSession();
und Ruhe im Karton


----------



## y0dA (4. Feb 2008)

SlaterB hat gesagt.:
			
		

> woher weißt du denn, dass Receiver ein persistentes Objekt ist?
> du hast hier nichts davon gepostet,
> 
> teste mal, ob receiver transient ist oder nicht:
> ...



In meinem letzten Satz stand doch, dass ich mir den Receiver zuvor aus der DB hole!
Jedoch habe ich nun ein contains gemacht und es liefert false - obwohl ich, wie schon erwähnt, mir dieses Objekt zuvor aus der DB lade - also es existiert in der DB.


----------



## SlaterB (4. Feb 2008)

DB ist teilweise egal, wichtig ist, ob es in der Session drin ist,
also wenn es nicht in der Session drin ist, dann hau es da wieder rein 
save oder update oder sowas


----------



## y0dA (4. Feb 2008)

Danke 
Wie handhabt man denn dann so eine Situation am besten?
Es kann ja nicht sein dass ich mir ein Objekt aus der DB lade und des dann mittels save/update erst Hibernate bekannt machen kann?


----------



## SlaterB (4. Feb 2008)

achso, nun dann musst du eben herausfinden, warum das Objekt nicht (mehr) in der Session ist,

vielleicht mit einer anderen Session geladen, andere Transaktion (weiß nicht ob sich das auswirkt), session.clear() zwischendurch usw.

prüfe von dem Zeitpunkt des Ladens an Schritt für Schritt, wann das Objekt noch drin ist und wann nicht mehr,
auch mit hashCode() vergleichen, ob es die gleiche Session ist


----------



## y0dA (4. Feb 2008)

Argh..
Ich mache es ja immer so dass ich dort wo ich meine DAOSsbenutze eben die Session öffne und danach wieder schließe.

Und natürlich ist jene Session bei welcher in die DB geschrieben wird, nicht jene, mit welcher ich den Receiver geladen habe (die habe ich zu dem Zeitpunkt schon lange geschlossen, da der Receiver schon um einiges früher geladen wird).

Mal wieder heftig geowned hier 

Ich danke dir, dass du mein Brainlagg beendet hast.


----------

