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

使用deepCopy复制实体触发am_location表key_列非空约束异常,是否需自定义实现?

实体复制触发数据库非空约束错误的解决方案

问题背景

界面中“复制”按钮的代码实现:

public void execute() {
    BaseUuidEntity entity = (BaseUuidEntity) metadata.getTools().deepCopy(target.getSingleSelected());
    entity.setId(UUID.randomUUID());
    screenBuilders.editor(target)
            .newEntity(entity)
            .build()
            .show();
}

平台内置的deepCopy()方法:

public <T extends Entity> T deepCopy(T source) {
    CachingEntitiesHolder entityFinder = new CachingEntitiesHolder();
    Entity destination = entityFinder.create(source.getClass(), source.getId());
    deepCopy(source, destination, entityFinder);

    return (T) destination;
}

使用deepCopy()复制“主仓库”实体时,出现数据库错误:am_location关联表的key_列存在NULL值,违反NOT NULL约束。调试发现对应实体的refLocation属性被复制为null,而Location表的KEY字段设置了非空约束,导致复制后的实体无法保存。

尝试替换为copy()方法,但触发了未获取属性的IllegalStateException,且我的实体包含大量嵌套集合,copy()无法满足需求,只有deepCopy()符合场景但表现异常。

可行的解决方案

1. 先排查关联属性的加载状态

平台deepCopy()复制关联实体时,如果源实体的关联属性未被加载(比如延迟加载的关联对象),复制后就会出现null值。先确认:

  • 复制前是否已通过dataManager.load()或视图配置,加载了源实体的refLocation属性
  • 示例代码:
BaseUuidEntity source = target.getSingleSelected();
// 用包含关联属性的视图加载源实体
source = dataManager.load(source.getId()).view("warehouse-with-refLocation").one();

2. 复制后手动补全非空属性

如果平台复制逻辑确实遗漏了非空字段,可以在deepCopy()之后手动修复:

public void execute() {
    BaseUuidEntity source = target.getSingleSelected();
    // 确保关联属性已加载
    source = dataManager.load(source.getId()).view("warehouse-with-refLocation").one();
    
    BaseUuidEntity copiedEntity = (BaseUuidEntity) metadata.getTools().deepCopy(source);
    // 补全非空的refLocation属性
    if (copiedEntity instanceof WarehouseEntity) {
        WarehouseEntity warehouse = (WarehouseEntity) copiedEntity;
        if (warehouse.getRefLocation() == null) {
            warehouse.setRefLocation(source.getRefLocation());
        }
    }
    
    copiedEntity.setId(UUID.randomUUID());
    screenBuilders.editor(target)
            .newEntity(copiedEntity)
            .build()
            .show();
}

3. 扩展平台的deepCopy()方法

如果多个实体都存在类似问题,可以继承平台的实体工具类,重写deepCopy()方法统一处理非空字段:

public class CustomEntityTools extends EntityTools {
    @Override
    public <T extends Entity> T deepCopy(T source) {
        T copied = super.deepCopy(source);
        
        // 针对WarehouseEntity处理非空字段
        if (copied instanceof WarehouseEntity) {
            WarehouseEntity warehouse = (WarehouseEntity) copied;
            if (warehouse.getRefLocation() == null && source instanceof WarehouseEntity) {
                warehouse.setRefLocation(((WarehouseEntity) source).getRefLocation());
            }
        }
        
        // 其他实体的处理逻辑...
        return copied;
    }
}

然后在项目中替换使用自定义的工具类。

4. 仅针对异常实体编写自定义复制逻辑

如果只有少数实体出问题,可以单独为这些实体编写复制方法,复用平台的嵌套集合复制能力:

private WarehouseEntity copyWarehouse(WarehouseEntity source) {
    // 用平台deepCopy处理嵌套集合
    WarehouseEntity copied = metadata.getTools().deepCopy(source);
    // 修复非空字段
    copied.setRefLocation(source.getRefLocation());
    copied.setId(UUID.randomUUID());
    return copied;
}

5. 检查实体映射与数据库约束的一致性

确认实体类中refLocation属性是否添加了@NotNull注解,数据库表的非空约束是否和实体配置一致。映射配置错误也可能导致复制时属性丢失。

结论

不需要立刻完全自行实现复制方法,优先尝试确保关联属性加载和复制后手动补全字段的方案,这样能最大程度复用平台的嵌套集合复制逻辑。只有当平台复制逻辑存在多处无法修复的缺陷时,再考虑完全自定义复制方法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 00:35:26