下面描述的内容在Sping Boot 2/Hibernate 5中有效,但在迁移到Hibernate 6/Spring Boot 3时停止工作。
我有一个Hibernate托管实体,它有一个集合属性(List或Map,并不重要),使用AttributeConverter从DB转换值。
现在的问题是:当值被更新时,这不再被检测为改变,并且在事务结束时,实体不被更新(假设仅该属性改变)。集合属性不再被标记为脏。
(Code已简化,仅用作说明)
@Entity
@Table(name = "person")
public class Person {
@Id
private int id;
...
@Convert(converter = HashMapConverter.class)
private Map<String, Object> attributes = new HashMap<>();
...
}
public class HashMapConverter implements AttributeConverter<HashMap<String, Object>, String> {
private final ObjectMapper mapper = new ObjectMapper();
@Override
public String convertToDatabaseColumn(HashMap<String, Object> map) {
try {
return mapper.writeValueAsString(map);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
@Override
public HashMap<String, Object> convertToEntityAttribute(String string) {
try {
return mapper.readValue(string, new TypeReference<>() {});
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
我做了一些调查,Hibernate中的CollectionJavaType是可变的,Entity也是可变的,但是似乎集合属性的BasicAttributeMapping将该属性标记为不可变(ImmutableMutability),因此EntityInitialiser不进行复制或进行浅复制,这似乎导致更改无法被检测到。
如果我向转换器添加一个特定的MutabilityPlan,将转换器标记为可变,则会正确检测到更改,属性被标记为脏,并且DB中的实体会更新。
@Mutability(MyPlan.class)
...
class MyPlan extends MutableMutabilityPlan<HashMap<String, Object>> {
@Override
protected HashMap<String, Money> deepCopyNotNull(HashMap<String, Object> value) {
return new HashMap(value);
}
}
但这带来了一个新问题:通过CollectionJavaType的DirtyCheck现在总是将属性标记为dirty,即使没有进行任何更改。
原来的代码是否仍然可以在Hibernate 6中工作?或者我真的需要为我拥有的每个转换器添加一个特定的MutabilityPlan?
1条答案
按热度按时间rdlzhqv91#
听起来您遇到了此问题https://hibernate.atlassian.net/browse/HHH-16081