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

如何映射共享列的实体并支持增改?解决JPA重复列映射错误

解决JPA多共享列实体关联的重复列映射错误

问题场景

配置多共享列的实体关联时触发错误:
Repeated column in mapping for entity: Aula column: no_entity (should be mapped with insert="false" update="false")

原始实体类代码:

@Entity
@Table(name = "AULAS")
public class Aula {
    @Id
    private String cveAula;

    // 该关联非空
    @ManyToOne(optional = false)
    @JoinColumns({
            @JoinColumn(name = "NO_PAIS", referencedColumnName = "NO_PAIS", nullable = false),
            @JoinColumn(name = "NO_ENTIDAD", referencedColumnName = "NO_ENTIDAD", nullable = false),
            @JoinColumn(name = "NO_DELEGACION", referencedColumnName = "NO_DELEGACION", nullable = false)
    })
    private DelegacionMunicipio delegacionMunicipio;

    // 该关联可为空,复用delegacionMunicipio的外键字段
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "NO_PAIS", referencedColumnName = "NO_PAIS"),
            @JoinColumn(name = "NO_ENTIDAD", referencedColumnName = "NO_ENTIDAD"),
            @JoinColumn(name = "NO_DELEGACION", referencedColumnName = "NO_DELEGACION"),
            @JoinColumn(name = "NO_LOCALIDAD", referencedColumnName = "NO_LOCALIDAD")
    })
    private Localidad localidad;

    // 与localidad关联逻辑类似
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "NO_PAIS", referencedColumnName = "NO_PAIS"),
            @JoinColumn(name = "NO_ENTIDAD", referencedColumnName = "NO_ENTIDAD"),
            @JoinColumn(name = "NO_DELEGACION", referencedColumnName = "NO_MUNICIPIO"),
            @JoinColumn(name = "NO_ASENTAMIENTO", referencedColumnName = "NO_ASENTAMIENTO")
    })
    private CodigoPostal entCodigoPostal;
}

数据库表结构:

CREATE TABLE DELEGACIONES_MUNICIPIOS
(
    NO_PAIS       NUMBER(3) NOT NULL,
    NO_ENTIDAD    NUMBER(3) NOT NULL,
    NO_DELEGACION NUMBER(3) NOT NULL,
    PRIMARY KEY (NO_PAIS, NO_ENTIDAD, NO_DELEGACION)
);

CREATE TABLE LOCALIDADES
(
    NO_PAIS       NUMBER(3) NOT NULL,
    NO_ENTIDAD    NUMBER(3) NOT NULL,
    NO_DELEGACION NUMBER(4) NOT NULL,
    NO_LOCALIDAD  NUMBER(4) NOT NULL,
    PRIMARY KEY (NO_PAIS, NO_ENTIDAD, NO_DELEGACION, NO_LOCALIDAD)
);

CREATE TABLE CODIGOS_POSTALES
(
    NO_PAIS       NUMBER(3) NOT NULL,
    NO_ENTIDAD    NUMBER(3) NOT NULL,
    NO_DELEGACION NUMBER(4) NOT NULL,
    NO_ASENTAMIENTO  NUMBER(4) NOT NULL,
    PRIMARY KEY (NO_PAIS, NO_ENTIDAD, NO_DELEGACION, NO_ASENTAMIENTO)
);

CREATE TABLE AULAS
(
    CVE_AULA      VARCHAR2(6) NOT NULL PRIMARY KEY,
    NO_PAIS       NUMBER(3)   NOT NULL,
    NO_ENTIDAD    NUMBER(3)   NOT NULL,
    NO_DELEGACION NUMBER(3)   NOT NULL,
    NO_LOCALIDAD  NUMBER(4),
    NO_ASENTAMIENTO  NUMBER(4)
);

当前已通过新增单独字段+配置insertable = false, updatable = false实现正常运行,但希望直接以对象形式处理关联,无需单独定义noLocalidad这类字段。

错误原因

JPA不允许数据库中同一列被多个可执行插入/更新操作的关联映射。Aula实体中,NO_PAIS、NO_ENTIDAD、NO_DELEGACION这三个列同时被delegacionMunicipio、localidad、entCodigoPostal三个关联引用,且默认情况下这些关联的列都具备插入/更新权限,导致冲突。

解决方案

指定其中一个关联(这里选择delegacionMunicipio,因为它是非空的主关联)负责共享列的插入和更新,其他关联的共享列则设置insertable = false, updatable = false,同时保留对象关联,无需新增单独字段。

修改后的实体类代码:

@Entity
@Table(name = "AULAS")
public class Aula {
    @Id
    private String cveAula;

    // 主关联,负责共享列的插入与更新
    @ManyToOne(optional = false)
    @JoinColumns({
            @JoinColumn(name = "NO_PAIS", referencedColumnName = "NO_PAIS", nullable = false),
            @JoinColumn(name = "NO_ENTIDAD", referencedColumnName = "NO_ENTIDAD", nullable = false),
            @JoinColumn(name = "NO_DELEGACION", referencedColumnName = "NO_DELEGACION", nullable = false)
    })
    private DelegacionMunicipio delegacionMunicipio;

    // 关联localidad,共享列设为不可插入/更新,专属列NO_LOCALIDAD正常映射
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "NO_PAIS", referencedColumnName = "NO_PAIS", insertable = false, updatable = false),
            @JoinColumn(name = "NO_ENTIDAD", referencedColumnName = "NO_ENTIDAD", insertable = false, updatable = false),
            @JoinColumn(name = "NO_DELEGACION", referencedColumnName = "NO_DELEGACION", insertable = false, updatable = false),
            @JoinColumn(name = "NO_LOCALIDAD", referencedColumnName = "NO_LOCALIDAD")
    })
    private Localidad localidad;

    // 关联CodigoPostal,共享列设为不可插入/更新,专属列NO_ASENTAMIENTO正常映射
    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "NO_PAIS", referencedColumnName = "NO_PAIS", insertable = false, updatable = false),
            @JoinColumn(name = "NO_ENTIDAD", referencedColumnName = "NO_ENTIDAD", insertable = false, updatable = false),
            @JoinColumn(name = "NO_DELEGACION", referencedColumnName = "NO_MUNICIPIO", insertable = false, updatable = false),
            @JoinColumn(name = "NO_ASENTAMIENTO", referencedColumnName = "NO_ASENTAMIENTO")
    })
    private CodigoPostal entCodigoPostal;
}

说明

  1. 主关联delegacionMunicipio保持原有配置,负责NO_PAIS、NO_ENTIDAD、NO_DELEGACION的插入和更新操作;
  2. 其他关联的共享列添加insertable = false, updatable = false,告知JPA这些列由主关联维护,当前关联仅用于查询和对象关联展示;
  3. 专属列(如NO_LOCALIDAD、NO_ASENTAMIENTO)无需单独定义字段,直接通过关联对象的赋值来维护,JPA会自动映射对应列的值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 19:52:03