Hibernate ClassCastException org.hibernate.type.SerializableType 无法转换为 org.hibernate.type.VersionType

Hibernate ClassCastException org.hibernate.type.SerializableType cannot be cast to org.hibernate.type.VersionType

当我尝试 运行 单元测试时出现奇怪的异常。这是堆栈跟踪:

javax.persistence.PersistenceException: [PersistenceUnit: testPU] Unable to build Hibernate SessionFactory
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.persistenceException(EntityManagerFactoryBuilderImpl.java:1249)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.access0(EntityManagerFactoryBuilderImpl.java:120)
     ... more
Caused by: org.hibernate.MappingException: Could not instantiate persister org.hibernate.persister.entity.SingleTableEntityPersister
    at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:174)
    at org.hibernate.persister.internal.PersisterFactoryImpl.createEntityPersister(PersisterFactoryImpl.java:135)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:401)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:857)
    ... 39 more
Caused by: java.lang.ClassCastException: org.hibernate.type.SerializableType cannot be cast to org.hibernate.type.VersionType
    at org.hibernate.tuple.PropertyFactory.buildVersionProperty(PropertyFactory.java:181)
    at org.hibernate.tuple.entity.EntityMetamodel.<init>(EntityMetamodel.java:218)
    at org.hibernate.persister.entity.AbstractEntityPersister.<init>(AbstractEntityPersister.java:520)
    at org.hibernate.persister.entity.SingleTableEntityPersister.<init>(SingleTableEntityPersister.java:148)
    at sun.reflect.GeneratedConstructorAccessor29.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at org.hibernate.persister.internal.PersisterFactoryImpl.create(PersisterFactoryImpl.java:163)
    ... 43 more

以下是我正在使用的库和框架:

  1. JPA 2.0
  2. org.hibernate:hibernate-entitymanager:4.3.5.Final
  3. com.h2数据库:h2:1.4.188
  4. junit:junit:4.11
  5. Intellij IDE(我只是运行在这里测试)
  6. org.hibernate:hibernate-envers:4.3.5.Final

好吧,我敢打赌任何看到这个的人都想看到 persistense.xml 文件,所以这里是:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>

这里有很多 类 所以我把它们删掉了以保持可读性

        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;MODE=PostgreSQL;INIT=create schema if not exists test;DB_CLOSE_DELAY=-1" />
            <property name="javax.persistence.jdbc.user" value="sa" />
            <property name="javax.persistence.jdbc.password" value="" />
            <property name="hbm2ddl.auto" value="create" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect"/>
            <property name="hibernate.show_sql" value="false"/>
        </properties>
    </persistence-unit>
</persistence>

单元测试很基础。它只是按值查找记录。这是代码:

@Test
  public void testFindByNaturalKeyReturnsBusinessUnit() {
    final BusinessUnit businessUnit = mock(BusinessUnit.class);
    assertThat(businessUnitDao.findByNaturalKey(businessUnit.getNaturalKey()).getId(), is(businessUnit.getId()));
  }

最后,实体真的很复杂。我不确定发布代码是否有帮助。我想实体中存在错误关系,所以我正在调查。

好的,有答案了。实体 class 对某些字段使用了 JodaTime。这需要 persistence.xml 文件设置一些额外的属性。

JodaTime 字段示例:

@javax.persistence.Column(name = "active_date")
private org.joda.time.DateTime activeDate;

最后,固定的 persistence.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
    <persistence-unit name="testPU" transaction-type="RESOURCE_LOCAL">
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <exclude-unlisted-classes>true</exclude-unlisted-classes>

这里有很多 class,所以我将它们删掉以保持可读性

        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.h2.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:h2:mem:test;MODE=PostgreSQL;INIT=create schema if not exists test;DB_CLOSE_DELAY=-1" />
            <property name="javax.persistence.jdbc.user" value="sa" />
            <property name="javax.persistence.jdbc.password" value="" />
            <property name="hbm2ddl.auto" value="create" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL9Dialect"/>
            <property name="hibernate.show_sql" value="false"/>
            <property name="jadira.usertype.autoRegisterUserTypes" value="true"/>
            <property name="jadira.usertype.databaseZone" value="jvm"/>
            <property name="jadira.usertype.javaZone" value="jvm"/>
        </properties>
    </persistence-unit>
</persistence>