如何解决“HHH90000003: 使用DOM4J实体模式被认为是不推荐的”问题

7

我刚把我的项目的hibernate版本升级到了5.0.0.FINAL。但是我发现我收到了这个警告。我想摆脱它。我不知道它是否会影响我的应用程序。

2015-08-24 14:29:22.235  WARN   --- [           main] org.hibernate.orm.deprecation            : HHH90000003: Use of DOM4J entity-mode is considered deprecated

由于我从未显式使用实体模式,所以我在网上搜索了一下,但几乎没有关于它的信息。这是EntityMode枚举。由于不再有DOM4J模式,我怀疑如果我继续在5.0.0版本中使用hibernate,可能会在生产中出现错误。

我还在使用hibernate的envers。如果我禁用envers,警告也会消失。我同时使用spring和hibernate和envers。以下是它们的版本。

<spring.version>4.2.0.RELEASE</spring.version>
<hibernate.version>5.0.0.Final</hibernate.version>
<hibernate.envers.version>5.0.0.Final</hibernate.envers.version>
<hibernate-jpa-2.1-api.version>1.0.0.Final</hibernate-jpa-2.1-api.version>
<project.java.version>1.8</project.java.version>

这是我的hibernate-jpa配置。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="commonsEntityManagerFactory"
          class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="commonDataSource"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
        <property name="jpaDialect">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
        </property>

        <property name="jpaProperties">
            <props>
                <prop key="hibernate.ejb.interceptor">com.examples.dao.utils.AbstractEntityInterceptor</prop>
                <!--<prop key="hibernate.listeners.envers.autoRegister">false</prop>-->
                <prop key="hibernate.implicit_naming_strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl</prop>
                <prop key="hibernate.physical_naming_strategy">org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl</prop>
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.showSql">${hibernate.showSql}</prop>
                <prop key="hibernate.formatSql">${hibernate.formatSql}</prop>
                <prop key="hibernate.generate_statistics">${hibernate.generate_statistics}</prop>
                <prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>
                <prop key="hibernate.default_batch_fetch_size">${hibernate.default_batch_fetch_size}</prop>
                <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>
                <prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</prop>
                <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>
                <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>
                <prop key="org.hibernate.envers.audit_table_suffix">${org.hibernate.envers.audit_table_suffix}</prop>
                <prop key="javax.persistence.sharedCache.mode">${javax.persistence.sharedCache.mode}</prop>
            </props>
        </property>
        <property name="packagesToScan">
            <list>
                <value>com.examples.entity</value>
            </list>
        </property>
    </bean>

    <bean id="commonsTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="commonsEntityManagerFactory"/>
    </bean>

    <tx:annotation-driven transaction-manager="commonsTransactionManager"/>
    <context:component-scan base-package="com.examples.dao.*"/>

</beans>

这里是一个实体的例子。

@Entity
@Table(name = "T_USER")
@Access(AccessType.FIELD)
@Audited
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "C_USERNAME", unique = true)
    private String username;

    @Column(name = "C_PASSWORD")
    private String password;

    @Column(name = "C_EMAIL")
    private String email;

    // Getters && Setters etc
}

更新

我在github上创建了一个项目,展示了这种行为。经过一些调试,我发现警告信息是在ModelBinder#L2441上创建的。

以下是示例代码:

public class ModelBinder
...
    private void bindProperty(
            MappingDocument mappingDocument,
            AttributeSource propertySource,
            Property property) {
        property.setName( propertySource.getName() );

        if ( StringHelper.isNotEmpty( propertySource.getName() ) ) {
        // Here is the line that print outs the log I was mentioned
          DeprecationLogger.DEPRECATION_LOGGER.logDeprecationOfDomEntityModeSupport();
        }
...
    }
}

当我查看mappingDocument.getOrigin()的值时,它是Origin(name=envers,type=OTHER)。因此,我仍然怀疑envers引起了这个警告。
顺便说一下,如果您删除@Audit注释或使用我提到的属性,则此警告仍将消失。

1
据我所知,默认情况下Hibernate使用POJO模式。但是你可以通过@Tuplizer注释或<tuplizer />标签来覆盖它。但是由Envers创建的实体默认使用DOM。我在日志中看到与Envers实体大小相同数量的警告。但是我无法覆盖Envers实体模式。您可以在hibernate文档中找到有关tupilizer的额外信息。 - bhdrkn
需要明确的是,Envers使用MAP实体模式,而不是(已删除的)DOM4J实体模式。 - Steve Ebersole
@SteveEbersole那么,为什么当我禁用envers时警告消息被删除?您能指出证明envers正在使用MAP的源代码吗? - bhdrkn
如果我猜的话,Envers可能是在生成的XML中指定embed-xml?你得去看看。但无论如何,我向你保证,Envers使用的是EntityMode.MAP而不是EntityMode.DOM4J。 - Steve Ebersole
2
我根本没有使用Envers,但我仍然收到这个弃用警告。我正在使用单独的XML映射文档(没有注释)。XML映射文档已经被弃用了吗?还是这个测试只是过于急切? - David
显示剩余2条评论
3个回答

6

我认为这些消息是由ModelBinder中的错误导致的。应该使用getXmlNodeName而不是getName。我已经报告了这个问题,希望在下一个版本中能得到解决。无论如何,除了额外的日志行之外,没有任何其他后果。


请问您能提供问题链接吗? - Adam Michalik

1

我使用与@bhdrkn相同的环境

<!-- Jpa Entity Manager 配置 -->
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="database">
                <bean factory-method="getDatabase" class="net.gelif.core.persistence.Hibernates">
                    <constructor-arg ref="dataSource"/>
                </bean>
            </property>
        </bean>
    </property>
    <property name="packagesToScan">
        <array>
            <value>net.gelif.**.entity</value>
        </array>
    </property>
    <property name="sharedCacheMode" value="ENABLE_SELECTIVE"/>
    <property name="jpaProperties">
        <props>
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).HBM2DDL_AUTO}">update</prop><!-- hibernate.hbm2ddl.auto -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).DEFAULT_ENTITY_MODE}">pojo</prop><!-- hibernate.default_entity_mode -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).CURRENT_SESSION_CONTEXT_CLASS}">thread</prop><!-- hibernate.current_session_context_class -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).CACHE_REGION_FACTORY}">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop><!-- hibernate.cache.region.factory_class -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).USE_SECOND_LEVEL_CACHE}">true</prop><!-- hibernate.cache.use_second_level_cache -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).USE_QUERY_CACHE}">true</prop><!-- hibernate.cache.use_query_cache -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).SHOW_SQL}">false</prop><!-- hibernate.show_sql -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).MAX_FETCH_DEPTH}">3</prop><!-- hibernate.max_fetch_depth -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).IGNORE_EXPLICIT_DISCRIMINATOR_COLUMNS_FOR_JOINED_SUBCLASS}">false</prop><!-- hibernate.discriminator.ignore_explicit_for_joined -->
            <prop key="#{T(org.hibernate.cfg.AvailableSettings).USE_NEW_ID_GENERATOR_MAPPINGS}">true</prop><!-- hibernate.id.new_generator_mappings -->
            <prop key="#{T(org.hibernate.jpa.AvailableSettings).VALIDATION_MODE}">none</prop><!-- javax.persistence.validation.mode -->
            <prop key="#{T(org.hibernate.cache.ehcache.AbstractEhcacheRegionFactory).NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME}">cache/ehcache-hibernate-local.xml</prop><!-- net.sf.ehcache.configurationResourceName -->

            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).AUDIT_TABLE_PREFIX}"></prop><!-- org.hibernate.envers.audit_table_prefix 配置数据修改记录表名的前缀规则  默认值:空 -->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).AUDIT_TABLE_SUFFIX}">_audit</prop><!-- org.hibernate.envers.audit_table_suffix 配置数据修改记录表名的后缀规则  默认值:_AUD -->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).REVISION_FIELD_NAME}">revision</prop><!-- org.hibernate.envers.revision_field_name 配置数据修改记录表版本号字段名  默认值: REV -->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).REVISION_TYPE_FIELD_NAME}">revision_type</prop><!-- org.hibernate.envers.revision_type_field_name 配置数据修改记录表修改类型字段名  默认值: REVTYPE  . 0表示新增加,1修改 2删除 -->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).REVISION_ON_COLLECTION_CHANGE}">true</prop><!-- org.hibernate.envers.revision_on_collection_change 配置是否支持关联表修改时记录修改记录  默认值:true-->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).DO_NOT_AUDIT_OPTIMISTIC_LOCKING_FIELD}">true</prop><!-- org.hibernate.envers.do_not_audit_optimistic_locking_field 配置是否不对乐观锁字段修改时记录修改记录,即使用(@Version)字段  默认值:true-->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).STORE_DATA_AT_DELETE}">true</prop><!-- org.hibernate.envers.store_data_at_delete 配置是否在删除操作时,只保存id值还是全部的值。 默认值:false 只记录id-->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).DEFAULT_SCHEMA}"></prop><!-- org.hibernate.envers.default_schema 配置数据修改记录表的schema 默认值:null-->
            <prop key="#{T(org.hibernate.envers.configuration.EnversSettings).DEFAULT_CATALOG}"></prop><!-- org.hibernate.envers.default_catalog 配置数据修改记录表的catalog 默认值:null-->
        </props>
    </property>
</bean>

<!-- Spring Data Jpa配置, 扫描base-package下所有继承于Repository<T,ID>的接口 -->
<jpa:repositories base-package="net.gelif.ems.**.dao.**" repository-impl-postfix="Impl" entity-manager-factory-ref="entityManagerFactory" transaction-manager-ref="jpaTransactionManager"/>

<!-- 事务管理器配置, Jpa单数据源事务 -->
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

<!-- 使用annotation定义事务 -->
<tx:annotation-driven transaction-manager="jpaTransactionManager" proxy-target-class="true"/>

当我移除了实体中的 Hibernate Envers 设置和 @Audit 注解后,这些警告消失了。

我使用自定义的hibernate-envers设置,像这样,仍然会出现“HHH90000003:使用DOM4J实体模式被认为是不推荐使用”的警告。 <code> @Entity @RevisionEntity(GlobalRevisionListener.class) @Table(name = "global_revisions") public class GlobalRevisionEntity { ... } </code> - geewit
当我进行调试时,我发现AttributeSource propertySource是由CompositeIdentifierSingularAttributeSourceManyToOneImpl实现的,并且"getXmlNodeName"方法返回不为null。 - geewit
所有的“getXmlNodeName”方法都返回“revision”。 - geewit

0

我更新了代码但仍然存在错误,问题的最后一条评论指出有一个有问题的类。 - Marc-André Poulin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接