具有ehcache复制和Composite ID的Hibernate 5.3回归

时间:2019-04-04 10:18:28

标签: hibernate replication ehcache jgroups

我们正在使用以下组件

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:   找不到SessionFactory   [uuid = e440a601-e5d0-4e9d-b4ce-94105b545106,name = null]在   org.jgroups.Message.getObject(Message.java:383)位于   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)在   org.jgroups.protocols.pbcast.NAKACK.up(NAKACK.java:602)在   org.jgroups.protocols.VERIFY_SUSPECT.up(VERIFY_SUSPECT.java:155)在   org.jgroups.protocols.FD_SOCK.up(FD_SOCK.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)     在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(本机方法)处   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)     在   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.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.invoke0(本机方法)位于   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.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个常见框架   省略

TypeConfiguration中引发了错误,此错误自5.3起可用

1 个答案:

答案 0 :(得分:0)

为会话工厂命名时,可以修复此错误。在带有Tomcat的Spring Boot2中,这并不容易,因为默认情况下未启用tomcats jndi。

使用Spring Configuration类在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,这是一个类加载问题。如果将其从类路径中删除,则复制可以正常进行。