hibernate - 带有 ehcache 复制和复合 ID 的 Hibernate 5.3 回归
问题描述
我们正在使用以下组件
org.hibernate:hibernate-core:jar:5.3.7.Final:compile
org.hibernate:hibernate-ehcache:jar:5.3.7.Final:compile
net.sf.ehcache:ehcache:jar:2.10.6:compile
net.sf.ehcache:ehcache-jgroupsreplication:jar:1.7:compile
org.jgroups:jgroups:jar:3.6.6.Final:compile
我们有一个具有复合 ID 的实体:
@Entity
@Cache(region = ReplicatedCacheConfiguration.NAME, usage = CacheConcurrencyStrategy.READ_WRITE)
public class SpielErgebnis {
@EmbeddedId
protected SpielErgebnisId spielErgebnisId;
…
}
@Embeddable
public class SpielErgebnisId implements Serializable {
private static final long serialVersionUID = 1L;
public Integer spielId;
public Integer spielabschnittId;
…
}
或者缓存与 Jgroups 一起复制,但只发送失效消息:
replicateAsynchronously=true
replicatePuts=false
replicateUpdatesViaCopy=false
当这些实体之一发生更改并且必须发送“删除”消息时,接收方不接受该消息并引发异常:
原因:org.hibernate.HibernateException:找不到 SessionFactory [uuid=a1d8234c-1c14-4ba5-b429-d026fd2e6197,name=null]
这发生在我们从休眠版本 5.2.17 升级到 5.3.7 之后。它也发生在 5.4.x 上。
这是完整的堆栈跟踪:
java.lang.IllegalArgumentException:org.hibernate.HibernateException:在 org.jgroups.Message.getObject(Message.java:383) 处找不到 SessionFactory [uuid=e440a601-e5d0-4e9d-b4ce-94105b545106,name=null] org.jgroups.Message.getObject(Message.java:363) 在 net.sf.ehcache.distribution.jgroups.JGroupsCacheReceiver.receive(JGroupsCacheReceiver.java:64) 在 org.jgroups.JChannel.invokeCallback(JChannel.java:817)在 org.jgroups.JChannel.up(JChannel.java:741) 在 org.jgroups.stack.ProtocolStack.up(ProtocolStack.java:1029) 在 org.jgroups.protocols.pbcast.GMS.up(GMS.java:1045 ) 在 org.jgroups.protocols.FRAG.up(FRAG.java:149) 在 org.jgroups.protocols.pbcast.STABLE.up(STABLE.java:234) 在 org.jgroups.protocols.UNICAST.up(UNICAST. java:402) 在 org.jgroups.protocols.pbcast.NAKACK.handleMessage(NAKACK.java:第 790 章.java:310) 在 org.jgroups.protocols.MERGE2.up(MERGE2.java:237) 在 org.jgroups.protocols.Discovery.up(Discovery.java:295) 在 org.jgroups.protocols.TP.passMessageUp( TP.java:1577) 在 org.jgroups.protocols.TP$MyHandler.run(TP.java:1796) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) 在 java.util.concurrent.ThreadPoolExecutor $Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) 原因:org.hibernate.HibernateException:找不到 SessionFactory [uuid=e440a601-e5d0-4e9d-b4ce -94105b545106,name=null] 在 org.hibernate.type.spi.TypeConfiguration$Scope。readResolve(TypeConfiguration.java:328) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在 java.lang.reflect.Method.invoke(Method.java:498) 在 java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1260) 在 java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2078) 在 java. io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) 在 java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) 在 java.io.ObjectInputStream.readOrdinaryObject (ObjectInputStream.java:2069) 在 java.io.ObjectInputStream。readObject0(ObjectInputStream.java:1573) 在 java.io.ObjectInputStream.readArray(ObjectInputStream.java:1975) 在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1567) 在 java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java :2287) at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java .io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287) 在 java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) 在 java.io.ObjectInputStream。在 java.io.ObjectInputStream 处读取Object0(ObjectInputStream.java:1573)。defaultReadFields(ObjectInputStream.java:2287) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) 在 java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) 在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java :1573) 在 java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:2287) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2211) 在 java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) 在 java .io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) 在 java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) 在 java.util.ArrayList.readObject(ArrayList.java:797) 在 sun.reflect.NativeMethodAccessorImpl。在 sun.reflect.NativeMethodAccessorImpl 处调用0(本机方法)。invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass .java:1170) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2178) 在 java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) 在 java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573)在 java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) 在 org.jgroups.util.Util.objectFromByteBuffer(Util.java:485) 在 org.jgroups.Message.getObject(Message.java:380) ...省略20个常用框架43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2178) 在java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) at org.jgroups.util .Util.objectFromByteBuffer(Util.java:485) at org.jgroups.Message.getObject(Message.java:380) ... 省略了 20 个常用帧43) 在 java.lang.reflect.Method.invoke(Method.java:498) 在 java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1170) 在 java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:2178) 在java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2069) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) at org.jgroups.util .Util.objectFromByteBuffer(Util.java:485) at org.jgroups.Message.getObject(Message.java:380) ... 省略了 20 个常用帧readOrdinaryObject(ObjectInputStream.java:2069) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) at org.jgroups.util.Util.objectFromByteBuffer(Util .java:485) at org.jgroups.Message.getObject(Message.java:380) ... 省略了 20 个常用帧readOrdinaryObject(ObjectInputStream.java:2069) at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1573) at java.io.ObjectInputStream.readObject(ObjectInputStream.java:431) at org.jgroups.util.Util.objectFromByteBuffer(Util .java:485) at org.jgroups.Message.getObject(Message.java:380) ... 省略了 20 个常用帧
自 5.3 起可用的TypeConfiguration中引发错误
解决方案
当你给你的会话工厂一个名字时,你可以修复这个错误。在带有 Tomcat 的 Spring Boot2 中,这并不容易,因为默认情况下未启用 tomcats jndi。
使用 Spring 配置类在 Tomcat 中启用命名:
@Configuration
public class JndiConfig {
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
return new TomcatServletWebServerFactory() {
@Override
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
tomcat.enableNaming();
return super.getTomcatWebServer(tomcat);
}
};
}
}
然后在文件中添加一个属性application.properties
:
spring.jpa.properties.hibernate.session_factory_name=kicktipp
使用会话工厂名称,hibernate 很乐意排除消息并按其应有的方式工作。
附加:如果您仍然收到有关反射问题的错误,这可能是您的 IDE 中的类加载器问题。我使用 Intellij 并运行了我的 SpringBootApplication 的两个实例:
org.hibernate.property.access.spi.PropertyAccessException:通过持久属性的反射访问字段 [public java.lang.Integer ...SpielErgebnisId.spielId] 时出错
由于 spring-boot-devtools,这是一个类加载问题。如果将其从类路径中删除,则复制工作正常。
推荐阅读
- android - 将字符串资源转换为字符串
- nltk - 如何查看 NLTK 分类器训练方法
- java - 无法将二进制 (16) 类型的 UUID 添加到 SQL 中
- c++ - libc++ 的 std::basic_string 的 16 字节对齐模式背后的原因是什么?
- angular - Angular 6 - ng-dirty 和 ng-invalid 未按预期工作
- sql - 使用分区计算时显示 0
- javascript - 滚动到下一个div时更改位置?
- java - BlockingQueue 提供方法有时不会将项目添加到列表中
- javascript - 具有固定标题和可扩展行的可滚动表
- vba - 保存输出文件从 Microsoft Word 中的表中创建了特定的行和单元格