Hibernate 6.1.6中不再更新Hibernate实体上的Collection属性

wqsoz72f  于 2023-01-31  发布在  其他
关注(0)|答案(1)|浏览(159)

下面描述的内容在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?

相关问题