title: Hibernate cached detached objects
body: <p>I've been using my own object cache which works more or less: </p>
  
  <ol>
  <li>get objet by an fixed criteria (for example use by login name)</li>
  <li>store that object in a hashmap as it is used over and over again</li>
  <li>if in another session the same object is requested again i use the same object again.</li>
  <li>My objects are changed very rarly, and used extremly often (read only). I have hooks that clear my object cache if anything gets changed in the database.</li>
  </ol>
  
  <p>Now this works pretty well in most situations, but it causes some unwanted database hits in some cases. I've identified the following situation: </p>
  
  <ul>
  <li>I create an object (new Car()) </li>
  <li>assign a cached object to this object: car.setOwner(cache.lookup("Pete")) (this object was fetched from the database in another session 20 minutes ago)</li>
  <li>then I save the object </li>
  </ul>
  
  <p>At this point hibernate realizes, that that object is 'dettached' and during the nullify check it fetches that object from the database again.</p>
  
  <p>Is there a way to avoid that? Can I reattach an object to a session without hitting the database? "Trust me hiberante, this is a valid object, please remember it". </p>
  
  <p>Below I attach the stacktrace of this situation.</p>
  
  <p>Hibernate Version: 3.3.2.GA</p>
  
  <p>Cheers
  Reto</p>
  
  <pre><code>org.hibernate.jdbc.util.SQLStatementLogger.logStatement(SQLStatementLogger.java:115)
  org.hibernate.jdbc.AbstractBatcher.log(AbstractBatcher.java:444)
  org.hibernate.jdbc.AbstractBatcher.getPreparedStatement(AbstractBatcher.java:511)
  org.hibernate.jdbc.AbstractBatcher.prepareSelectStatement(AbstractBatcher.java:145)
  org.hibernate.persister.entity.AbstractEntityPersister.getDatabaseSnapshot(AbstractEntityPersister.java:1034)
  org.hibernate.engine.StatefulPersistenceContext.getDatabaseSnapshot(StatefulPersistenceContext.java:269)
  org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:212)
  org.hibernate.engine.ForeignKeys$Nullifier.isNullifiable(ForeignKeys.java:160)
  org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:92)
  org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:70)
  org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:311)
  org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
  org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
  org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
  org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
  org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
  org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
  org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
  org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:563)
  org.hibernate.impl.SessionImpl.save(SessionImpl.java:551)
  org.hibernate.impl.SessionImpl.save(SessionImpl.java:547)
  sun.reflect.GeneratedMethodAccessor271.invoke (Unknown Source)
  sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
  </code></pre>