3 Replies Latest reply on Apr 8, 2006 4:45 PM by Warg Krumpf

    2nd level cache fails with one-many-one relations

    Warg Krumpf Newbie

      i'm using TreeCache as the 2nd level cache with these 3 beans, which form a one-many-one relation:

      Car

      
      @Entity
      @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
      
      @Entity(optimisticLock = OptimisticLockType.VERSION)
      @Table(name = "CAR")
      
      public class Car extends BaseEntity implements java.io.Serializable {
      
       private List<FaxToCar> faxes;
      
      .....
      
       @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "car")
       @Cascade(value=CascadeType.DELETE_ORPHAN)
       @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
       public List<FaxToCar> getFaxes() {
       return faxes;
       }
      
      ....
      
       @Transient
       public String getFaxNameList() {
       List<FaxToCar> l = getFaxes();
       String s = "";
       for (FaxToCar car2 : l) {
       if (s.length() > 0) {
       s += ", ";
       }
       s += car2.getFax().getName();
       }
       return s;
       }
      }
      



      FaxToCar
      
      @Entity
      @Entity(optimisticLock = OptimisticLockType.VERSION)
      @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
      
      @Table(name = "FAX2CAR")
      
      public class FaxToCar extends BaseEntity implements java.io.Serializable {
      
      
      
      
       protected int seq;
      
       private Car car;
      
       private Fax fax;
      
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "car_id")
       public Car getCar() {
       return car;
       }
      
      
       public void setCar(Car car) {
       this.car = car;
       }
      
       @ManyToOne(fetch = FetchType.LAZY)
       @JoinColumn(name = "fax_id")
       public Fax getFax() {
       return fax;
       }
      
      
       public void setFax(Fax fax) {
       this.fax = fax;
       }
      
      
       public int getSeq() {
       return seq;
       }
      
      
       public void setSeq(int seq) {
       this.seq = seq;
       }
      
      }
      
      
      




      Fax
      @Entity
      @Entity(optimisticLock = OptimisticLockType.VERSION)
      @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
      
      @Table(name = "FAX")
      
      public class Fax extends BaseEntity implements java.io.Serializable {
      
       private List<FaxToCar> cars;
      
      ...
      
       @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "fax")
       @Cascade(value=CascadeType.DELETE_ORPHAN)
       @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
       @OrderBy("seq")
       public List<FaxToCar> getCars() {
       return cars;
       }
      ...
      
      


      After i deleted a "Fax", everything works as expected, unless i acces a "Car" which was previously cached, becasue it looks like its cached collection of "FaxToCar" references a now not longer instance of "Fax2Car", which was deleted because of "CascadeType.DELETE_ORPHAN".

      The stacktrace looks like this:

      10:54:22,171 INFO [STDOUT] Hibernate: select car0_.id as id12_, car0_.version as version12_, car0_.createdBy as createdBy12_, car0_.updatedBy as updatedBy12_,
      car0_.createdTime as createdT5_12_, car0_.updatedTime as updatedT6_12_, car0_.gf as gf12_, car0_.typ as typ12_, car0_.hersteller as hersteller12_, car0_.lack a
      lack12_, car0_.lack_code as lack11_12_, car0_.polster as polster12_, car0_.polster_code as polster13_12_, car0_.ez as ez12_, car0_.angebotspreis as angebot15_
      2_, car0_.vorbesitzer as vorbesi16_12_, car0_.km as km12_, car0_.neupreis as neupreis12_, car0_.behobenerschaden as behoben19_12_, car0_.differenzbesteuert as
      iffere20_12_, car0_.verkauft as verkauft12_, car0_.freitext as freitext12_ from CAR car0_ where 1=1 and (car0_.gf like ?)
      10:54:22,452 INFO [STDOUT] Hibernate: select faxtocar0_.id as id18_0_, faxtocar0_.version as version18_0_, faxtocar0_.createdBy as createdBy18_0_, faxtocar0_.
      pdatedBy as updatedBy18_0_, faxtocar0_.createdTime as createdT5_18_0_, faxtocar0_.updatedTime as updatedT6_18_0_, faxtocar0_.car_id as car8_18_0_, faxtocar0_.f
      x_id as fax9_18_0_, faxtocar0_.seq as seq18_0_ from FAX2CAR faxtocar0_ where faxtocar0_.id=?
      10:54:22,452 INFO [DefaultLoadEventListener] Error performing load command
      org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [de.foobar.hfax.entity.fax.FaxToCar#27908]
      at org.hibernate.ObjectNotFoundException.throwIfNull(ObjectNotFoundException.java:27)
      at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:128)
      at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:177)
      at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:87)
      at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:891)
      at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:859)
      at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:266)
      at org.hibernate.type.ManyToOneType.assemble(ManyToOneType.java:177)
      at org.hibernate.collection.PersistentBag.initializeFromCache(PersistentBag.java:140)
      at org.hibernate.cache.entry.CollectionCacheEntry.assemble(CollectionCacheEntry.java:35)
      at org.hibernate.event.def.DefaultInitializeCollectionEventListener.initializeCollectionFromCache(DefaultInitializeCollectionEventListener.java:130)
      at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:48)
      at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1695)
      at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
      at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
      at org.hibernate.collection.PersistentBag.iterator(PersistentBag.java:246)
      at de.foobar.hfax.entity.core.Car.getFaxNameList(Car.java:269)
      .....


      As a workaround, i'm manually evicting the offending collection out of the cache:
      public void removeFax(Fax fax) {
       manager.remove(fax);
       manager.flush();
       Session hs = ((HibernateSession)manager).getHibernateSession();
       hs.getSessionFactory().evictCollection("de.foobar.hfax.entity.core.Car.faxes");
       }


      Question: Bug or Feature ?

      TIA

      Marco