我正在使用以下转换器将一组字符串作为逗号分隔值(带转义)保存在单个 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 classX
, where the element type ofz
isZ
, the metamodel class must contain a declaration as follows:
if the collection type of
z
isjava.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/