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

Hibernate复合类型重叠列引发AnnotationException的解决方案是什么?

问题本质

Hibernate针对@Columns标注的复合属性内置了统一校验逻辑,要求所有内部@Column的insertable、updatable属性必须完全一致,不允许混合可写和只读列,该校验逻辑和HHH-6221的外键校验同源,目前官方没有推出类似@JoinColumnsOrFormulas的直接替代注解。

可行规避方案

方案1:统一@Columns内属性 + 单独维护共享列

将所有复合属性里的共享列currency_id统一设置为只读,单独新增一个普通持久化字段负责currency_id的写入和更新,避开校验规则:

// 单独维护currency_id的写入/更新逻辑
@Column(name = "currency_id")
private Long currencyId;

// 复合属性内的currency_id全部设为只读,所有@Column属性保持一致
@Columns(columns = {
    @Column(name = "currency_id", updatable = false, insertable = false),
    @Column(name = "fees")
})
private Money fees;

@Columns(columns = {
    @Column(name = "currency_id", updatable = false, insertable = false),
    @Column(name = "tax")
})
private Money tax;

操作注意:保存/更新实体时仅需给currencyId字段赋值即可,fees、tax实例中的币种属性会自动读取数据库字段完成映射,无需手动维护写入。

方案2:自定义AttributeConverter处理复合类型映射

通过JPA标准的类型转换器实现Money类型的自定义映射,完全绕过@Columns的校验逻辑:

// 自定义Money类型转换器
@Converter
public class MoneyConverter implements AttributeConverter<Money, Object[]> {
    @Override
    public Object[] convertToDatabaseColumn(Money money) {
        if (money == null) return new Object[]{null, null};
        // 共享currency_id由单独字段维护,此处仅返回金额值
        return new Object[]{null, money.getAmount()};
    }

    @Override
    public Money convertToEntityAttribute(Object[] dbData) {
        if (dbData == null || dbData.length != 2) return null;
        return new Money((Long) dbData[0], (BigDecimal) dbData[1]);
    }
}

实体类使用方式:

@Column(name = "currency_id")
private Long currencyId;

@Convert(converter = MoneyConverter.class)
@Columns(columns = {
    @Column(name = "currency_id", insertable = false, updatable = false),
    @Column(name = "fees")
})
private Money fees;

@Convert(converter = MoneyConverter.class)
@Columns(columns = {
    @Column(name = "currency_id", insertable = false, updatable = false),
    @Column(name = "tax")
})
private Money tax;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 00:15:03