简体   繁体   中英

Hibernate + Ehcache - IllegalArgumentException occurred calling getter of composite id

Searched a lot here, don't found any similar case, sorry if I'm wrong.

My context is a system that uses Hibernate and second level caching.

Previously used these versions (working on production with second level cache enable more than a year):

  • hibernate-ehcache-5.0.9.Final
  • ehcache-core-2.4.3
  • ehcache-2.9.0
  • hibernate-core-5.0.9.Final
  • others...

Now, upgrading the system, we change the version to:

  • hibernate-ehcache-5.2.10.Final
  • ehcache-2.10.3
  • hibernate-core-5.2.10.Final
  • others...

After updated the version of Hibernate and Ehcache started getting this exception above:

<exception name="IllegalArgumentException occurred calling getter of br.com.mycompany.myproject.mypackage.Employee.id">
    org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of br.com.mycompany.myproject.mypackage.Employee.id
    at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:64)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:230)
    at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:4720)
    at org.hibernate.type.EntityType.toLoggableString(EntityType.java:519)
    at org.hibernate.type.TypeHelper.toLoggableString(TypeHelper.java:439)
    at org.hibernate.cache.spi.entry.StructuredCacheEntry.destructure(StructuredCacheEntry.java:54)
    at org.hibernate.event.internal.DefaultLoadEventListener.processCachedEntry(DefaultLoadEventListener.java:612)
    at org.hibernate.event.internal.DefaultLoadEventListener.loadFromSecondLevelCache(DefaultLoadEventListener.java:602)
    at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:462)
    at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219)
    at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:116)
    at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89)
    at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1230)
    at org.hibernate.internal.SessionImpl.immediateLoad(SessionImpl.java:1088)
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:155)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:259)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:73)
    at br.com.mycompany.myproject.mypackage.Employee$$_jvstdd0_3.isActive(Employee_$$_jvstdd0_3.java)
    at br.com.mycompany.myproject.mypackage.Test.do(Test.java:30)
    at org.jpos.transaction.TxnSupport.prepare(TxnSupport.java:44)
    at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:549)
    at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:615)
    at org.jpos.transaction.TransactionManager.run(TransactionManager.java:291)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: java.lang.ClassCastException@32ed9549
    at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.hibernate.property.access.spi.GetterMethodImpl.get(GetterMethodImpl.java:41)
    ... 23 more
</exception>

My models entities (create for exemplify):

@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "myregion")
public class Employee implements Serializable { 

     private static final long serialVersionUID = 8467432396096896736L;

     @EmbeddedId
     private EmployeeID id;

     @ManyToOne(fetch = FetchType.LAZY)
     @JoinColumn(name = "id_company", nullable = false, insertable = false, updatable = false) 
     private Company company;

     gets & sets
     equals & hashcode
     ...
}
@Embeddable
public class EmployeeID implements Serializable { 

     private static final long serialVersionUID = 8467432396096896736L;

     @Column(name = "id_employee", nullable = false, insertable = false, updatable = false)
     private Long idEmployee;

     @Column(name = "id_company", nullable = false, insertable = false, updatable = false)
     private Integer idCompany;

     gets & sets
     equals & hashcode  
     ...
}

I verified (making tests) that this mistake occur when hibernate try to hydrate the entity from cache. If i turn off the cache its works.

So when rollback the versions, its works again with cache enabled.

It's occurs with all my entities have composite keys and are in second level cache

You have to debug and check why during hydration Hibernate throws the ClassCastException . It might be some bug.

However, I also noticed a weirdness in your mapping. Why does both the @EmbeddedId attributes and the @ManyToOne @JoinColumn are set to insertable = false and updatable = false .

This will make it impossible to ever persist and Employee or change its Company .

As I explained in this article , the @EmbeddedId should insert and update the composite identifier while the @ManyToOne should use @MapsId .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM