一尘不染

为什么将AttributeConverter用于集合会导致HHH015007:静态元模型字段注入中的参数非法

spring-boot

我正在使用以下转换器将一组字符串作为逗号分隔值(带有转义符)保留在单个VARCHAR数据库列中:

public class StringSetConverter implements AttributeConverter<Set<String>, String> {

   @Override
   public String convertToDatabaseColumn(Set<String> stringSet) {
      if (stringSet == null) {
         return null;
      }
      // remove null-strings and empty strings, escape commas
      return stringSet.stream().filter(Objects::nonNull).filter(s -> s.length() > 0)
                    .map(s -> s.replace(",", "\\,"))
                    .sorted().collect(Collectors.joining(","));
   }

   @Override
   public Set<String> convertToEntityAttribute(String dbString) {
      if (dbString == null) {
        return new HashSet<>();
      }
      Set<String> result = new HashSet<>();
      String[] items = dbString.split("(?<=[^\\\\]),");
      for (String item : items) {
         if (item.length() > 0) {
            result.add(item.replace("\\,", ","));
         }
      }
      return result;
   }
}

在JPA实体上的用法:

    @Column(name = "GRANTED_PRIVILEGES", nullable = false, length = 4000)
    @Convert(converter = StringSetConverter.class)
    private Set<String> grantedPrivileges;

    @Column(name = "DENIED_PRIVILEGES", nullable = false, length = 4000)
    @Convert(converter = StringSetConverter.class)
    private Set<String> deniedPrivileges;

转换器的工作原理非常好 -字符串集可以正确保留,并且可以读取而不会出现任何问题。

唯一的警告是启动使用这些实体的Spring Boot应用程序时 Hibernate记录错误

    ERROR o.h.m.i.MetadataContext : HHH015007: Illegal argument on static metamodel field injection : 
        anonymized.AuthorityDO_#grantedPrivileges; 
        expected type :  org.hibernate.metamodel.internal.SingularAttributeImpl; 
        encountered type : javax.persistence.metamodel.SetAttribute 
    ERROR  o.h.m.i.MetadataContext : HHH015007: Illegal argument on static metamodel field injection : 
        anonymized.AuthorityDO_#deniedPrivileges; 
        expected type :  org.hibernate.metamodel.internal.SingularAttributeImpl; 
        encountered type : javax.persistence.metamodel.SetAttribute

Hibernate的JPA有什么问题AttributeConverter?除了记录错误外,Hibernate最终可以与转换器一起很好地工作-
那么问题出在哪里,我该如何解决?


阅读 937

收藏
2020-05-30

共1个答案

一尘不染

您的映射是错误的,因为您尝试对奇异属性使用collection。根据JPA规范(请参见 6.2.1.1规范元模型 部分):

对于zclass声明的每个持久性具有集合值的属性X,其中元素类型zZ,元模型类必须包含如下声明:

  • 如果的收集类型zjava.util.Set,则

public static volatile SetAttribute<X, Z> z;

但是,Hibernate所期待的,你会使用@ElementCollection@OneToMany@ManyToMany协会收集属性。

我建议您对自定义类型使用一些包装器类:

public class StringSet {
  private Set<String> stringSet;
  // ...
}

public class StringSetConverter implements AttributeConverter<StringSet, String> {

    @Override
    public String convertToDatabaseColumn(StringSet stringSet) {
        // ...
    }

    @Override
    public StringSet convertToEntityAttribute(String dbString) {
       // ...
    }
}

@Column(name = "GRANTED_PRIVILEGES", nullable = false, length = 4000)
@Convert(converter = StringSetConverter.class)
private StringSet grantedPrivileges;
2020-05-30