You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Hibernate使用@Convert注解持久化时为何会执行额外更新?

问题:Hibernate保存带@Convert注解实体时出现额外Update操作

在使用Hibernate保存带有@Convert注解字段的简单实体时,执行insert操作后总会紧跟一条参数与insert完全相同的update操作,无法理解为何会出现这条额外查询,是否本该如此?若确实如此,原因是什么?

相关代码

待保存实体

@Entity
public class Building {

    @Id
    @GeneratedValue
    private Long id;

    @Convert(converter = AddressConverter.class)
    private Address address;
    // getter、setter等省略
}

需要转换的Address类

public class Address {

    private String street;

    private String city;
    // getter、setter等省略
}

转换器实现

@Converter
class AddressConverter implements AttributeConverter<Address, String> {

    @Override
    public String convertToDatabaseColumn(Address attribute) {
        return attribute.getStreet() + " " + attribute.getCity();
    }

    @Override
    public Address convertToEntityAttribute(String dbData) {
        String[] data = dbData.split(" ");
        Address address = new Address();
        address.setStreet(data[0]);
        address.setCity(data[1]);
        return address;
    }
}

执行日志

18:52:14.959 [main] DEBUG org.hibernate.SQL - insert into building (address, id) values (?, ?) 
18:52:14.960 [main] TRACE org.hibernate.orm.jdbc.bind - binding parameter [1] as [VARCHAR] - [test-street test-city] 
18:52:14.961 [main] TRACE org.hibernate.orm.jdbc.bind - binding parameter [2] as [BIGINT] - [1] 
18:52:14.962 [main] DEBUG org.hibernate.SQL - update building set address=? where id=? 
18:52:14.964 [main] TRACE org.hibernate.orm.jdbc.bind - binding parameter [1] as [VARCHAR] - [test-street test-city] 
18:52:14.964 [main] TRACE org.hibernate.orm.jdbc.bind - binding parameter [2] as [BIGINT] - [1] 

原因分析与解决方法

这种额外的update是Hibernate的脏检查机制导致的,核心问题出在转换器的实现上:

  • Hibernate执行insert后,会将数据库中存储的字符串反向转换回Address对象(通过convertToEntityAttribute方法),然后和内存中原先的Address对象做对比。
  • 你的convertToEntityAttribute方法每次都会新建一个Address实例,而Java中默认的对象对比是引用对比,两个不同的实例会被Hibernate判定为属性发生了变化,触发脏检查,进而执行update操作。

解决方法很简单:

  • 给Address类实现equals和hashCode方法,基于street和city这两个字段的值做比较,这样Hibernate就能正确识别出两个对象的内容是否一致,不会误判为脏数据,也就不会触发多余的update。

内容的提问来源于stack exchange,提问作者Piterowsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 23:31:04