【问题标题】:JavaTypeDescriptorRegistry - Could not find matching type descriptor for requested Java classJavaTypeDescriptorRegistry - 找不到请求的 Java 类的匹配类型描述符
【发布时间】:2015-12-24 01:31:58
【问题描述】:

我有一个项目运行没有问题,除了这个警告消息:

WARN  org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry - Could not find matching type descriptor for requested Java class [java.util.List]; using fallback enviroment

为什么我会收到此消息?我怎样才能禁用它?

我正在使用:

spring webmvc 4.2.1
hibernate-core 5.0.1

出现此消息是因为我使用的是 JPA 2.1 AttributeConverter。

【问题讨论】:

  • 有同样的问题;我正在使用 10+ AttributeConverters,但似乎只有其中两个受到影响。其他的 AttributeConverter 从简单类型转换为数据库列(例如数组),但这两个使用复杂类型(例如 POJO)到字符串(Json)转换。

标签: hibernate spring-mvc


【解决方案1】:

虽然两个答案都是合乎逻辑且正确的,但都没有解决上述问题中的实际问题!

java.util.List 出现此错误,您既不能编写 equals/hashcode 实现,也不能扩展 Serializable,在这里定义 AbstractTypeDescriptor 毫无意义。

您收到此错误仅仅是因为接口 List 在 Java 中不是 Serializable,您必须选择一个实现。

ArrayListLinkedList 等具体类型是 Serializable,您可以使用它们(打破基于接口的编程)或创建自己的 List 实现来扩展/实现 Serializable(没有内置的然后可以使用具体的List 实现)。

【讨论】:

    【解决方案2】:

    从 Hibernate 5.2.7(2017 年 1 月 24 日)开始,此警告更改为:

    警告 org.hibernate.type.descriptor.java.JavaTypeDescriptorRegistry - HHH000481:遇到的 Java 类型 [class SomeClass] for which 我们找不到 JavaTypeDescriptor 并且它似乎没有 实现equals和/或hashCode。这可能导致显着 执行相等/脏检查时的性能问题涉及 这种 Java 类型。考虑注册一个自定义 JavaTypeDescriptor 或 至少实现equals/hashCode。

    所以,有以下解决方案:

    1) 确保您的类型实现了equalshashcode,并使用Immutable.class 对其进行注释,以防它是不可变的。 Hibernate 将使用回退 (defined here)。

    2) 实现特定的 java-type-descriptor,如 SomePersistentClassTypeDescriptor:

    JavaTypeDescriptorRegistry.INSTANCE
                              .addDescriptor(new SomePersistentClassTypeDescriptor());
    

    您可以扩展AbstractTypeDescriptor。如果您的类型是不可变的,例如:

    public class SomePersistentClassTypeDescriptor
          extends AbstractTypeDescriptor<SomePersistentClass> {
    
        public SomePersistentClassTypeDescriptor() {
            super(SomePersistentClass.class);
            }
    
        @Override
        public String toString(SomePersistentClassvalue) {
            return (value == null) ? null : value.toString();
            }
    
        @Override
        public SomePersistentClassfromString(String string) {
            return (string == null) ? null : SomePersistentClass.getInstance(string);
            }
    
        @Override
        public <X> X unwrap(SomePersistentClass value, Class<X> type, WrapperOptions options) {
            if (value == null) return null;
            else if (String.class.isAssignableFrom(type)) {
                return (X)value.toString();
                }
            else throw unknownUnwrap(type);
            }
    
        @Nullable
        @Override
        public <X> SomePersistentClass wrap(X value, WrapperOptions options)
            {
            if (value == null) return null;
            if (String.class.isInstance(value)) {
                return SomePersistentClass.getInstance(((String)value));
                }
            throw unknownWrap(value.getClass());
            }
        }
    

    但是,如果您的类型是可变的,请提供您自己的 MutabilityPlan

    public class SomePersistentClassTypeDescriptor
          extends AbstractTypeDescriptor<SomePersistentClass> {
    
        public SomePersistentClassTypeDescriptor() {
            super(SomePersistentClass.class, new MyMutabilityPlan());
            }
    ...
    }
    

    3) 使SomePersistentClass 实现可序列化。然后 Hibernate 会使用序列化对象的字节数组比较进行脏检查等,这不是很好。


    另见:

    【讨论】:

      【解决方案3】:

      如果您的转换器应该转换的类型没有实现Serializable、不是enum 也不是one of the types Hibernate 知道如何转换,您会收到此警告。一旦您设置了转换器应该转换的类型Serializable,警告就会消失。

      查看 Hibernate 代码,JavaTypeDescriptor 的目的似乎是提供有关如何序列化某些类型以及是否或如何进行深拷贝的信息。因为 Hibernate 对 it makes some guesses 的类型一无所知。如果您愿意,您可以通过自己提供JavaTypeDescriptor 来帮助 Hibernate。有一个Singleton

      【讨论】:

      • 简单地创建类型 Serializable 将使 Hibernate 使用序列化对象的字节数组比较进行脏检查(除其他外)。所以一定要知道你在做什么。
      猜你喜欢
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-20
      相关资源
      最近更新 更多