JPA / Hibernate: предупреждения при использовании пользовательского набора строк / преобразователя строк - PullRequest
1 голос
/ 23 апреля 2020

Я использую следующий конвертер для сохранения набора строк в виде значений, разделенных запятыми (с экранированием) в одном столбце базы данных 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;

Конвертер работает очень хорошо - набор строк правильно сохраняется и может быть прочитан без проблем.

Единственное предостережение - это ошибки , которые Журнал Hibernate s при запуске приложения Spring Boot, которое использует следующие объекты:

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 в конечном итоге хорошо работает с конвертером - так в чем же проблема и как я могу ее исправить?

1 Ответ

0 голосов
/ 23 апреля 2020

Ваше отображение неверно, потому что вы пытаетесь использовать коллекцию для единственного атрибута. Согласно спецификации JPA (см. Раздел 6.2.1.1 Каноническая метамодель ):

Для каждого постоянного атрибута со значением коллекции z, объявленного классом X, где элемент тип z равен Z, класс метамодели должен содержать объявление следующим образом:

  • если тип коллекции z равен java.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;
...