Hibernate + Ehcache - IllegalArgumentException 发生调用复合 id 的 getter

Posted

技术标签:

【中文标题】Hibernate + Ehcache - IllegalArgumentException 发生调用复合 id 的 getter【英文标题】:Hibernate + Ehcache - IllegalArgumentException occurred calling getter of composite id 【发布时间】:2017-09-01 00:25:07 【问题描述】:

在这里搜索了很多,没有找到类似的案例,如果我错了,请见谅。

我的上下文是一个使用 Hibernate 和二级缓存的系统。

以前使用过这些版本(在生产中使用二级缓存启用一年多):

hibernate-ehcache-5.0.9.Final ehcache-core-2.4.3 ehcache-2.9.0 hibernate-core-5.0.9.Final 其他...

现在,升级系统,我们将版本改为:

hibernate-ehcache-5.2.10.Final ehcache-2.10.3 hibernate-core-5.2.10.Final 其他...

更新Hibernate和Ehcache版本后开始出现上述异常:

<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>

我的模型实体(创建示例):

@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  
     ...


我验证(进行测试)当休眠尝试从缓存中水合实体时会发生此错误。如果我关闭缓存它的工作。

因此,当回滚版本时,它会在启用缓存的情况下再次运行。

发生这种情况的所有实体都有复合键并且在二级缓存中

【问题讨论】:

【参考方案1】:

您必须调试并检查为什么在水合期间 Hibernate 会抛出 ClassCastException。这可能是一些错误。

但是,我也注意到您的映射有一个奇怪之处。为什么@EmbeddedId属性和@ManyToOne@JoinColumn都设置为insertable = falseupdatable = false

这将导致永远无法坚持和Employee 或更改其Company

正如我在 this article 中解释的那样,@EmbeddedId 应该插入和更新复合标识符,而 @ManyToOne 应该使用 @MapsId

【讨论】:

我已经使用@MapsId 查看了您所说的映射,但错误仍在继续(仅提一下)。但是,作为证据,我将注释从“get”方法更改为属性。错误更改,现在是:"Error accessing field private by reflection for persistent property id : [Ljava.lang.Object;@715ef487"&gt;" "Caused by: java.lang.IllegalArgumentException: Can not set... field id to [Ljava.lang.Object;" 你见过吗? hibernate.atlassian.net/browse/HHH-10618 我不知道这个问题。如果你可以使用our templates 复制它,你应该打开一个问题。

以上是关于Hibernate + Ehcache - IllegalArgumentException 发生调用复合 id 的 getter的主要内容,如果未能解决你的问题,请参考以下文章

HIbernate 3.5.1 - 我可以加入 EHCache 2.0.1 吗?

Hibernate 和 EHCache:maxElementsInMemory 是如何工作的?

Hibernate + EhCache = java.io.NotSerializableException

如何使用 Spring 清除所有 Hibernate 缓存(ehcache)?

Hibernate + Ehcache - IllegalArgumentException 发生调用复合 id 的 getter

hibernate二级缓存