hibernate - 使用 AttributeConverter 收集日志 ERROR HHH015007 : Illegal argument on static metamodel field injection

标签 hibernate spring-boot jpa spring-data-jpa

我正在使用以下转换器将一组字符串作为逗号分隔值(带转义)保存在单个 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 最终可以很好地与转换器配合使用 - 那么问题出在哪里,我该如何解决?

最佳答案

您的映射是错误的,因为您尝试对单一属性使用集合。根据 JPA 规范(参见 6.2.1.1 Canonical Metamodel 部分):

For every persistent collection-valued attribute z declared by class X, where the element type of z is Z, the metamodel class must contain a declaration as follows:

  • if the collection type of z is java.util.Set, then

    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;

关于hibernate - 使用 AttributeConverter 收集日志 ERROR HHH015007 : Illegal argument on static metamodel field injection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61385330/

相关文章:

hibernate - 在加载域之前修改gorm映射

java - 如何使用java将doc、pdf、图片文件保存到mysql数据库?

java - 错误: Column 'col_name' not found with createSQLQuery

spring-boot - 如何将 Web 应用程序文件夹加载到 docker 容器

java - 防止跨多个服务器重复 POST API 调用

java - 运行应用程序时tomcat未启动

java - FetchType = Lazy 且可选 = false 在 JPA 中不起作用

java - 使用@MapsId 在双向@OneToOne 上级联

java - 我可以在运行时创建的表上使用 JPA/EJB3 吗?

mysql - JPQL中的BINARY运算符等价的是什么?