JPA实体映射报错:idTipoDoctoEntrada列重复,需支持增改
解决JPA自关联映射字段重复报错问题
问题详情
数据表存在自关联关系,执行插入、修改操作时触发如下报错:
Column 'idTipoDoctoEntrada' is duplicated in mapping for entity 'com.provider.fatoria.model.ConfigPergunta' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
需保留字段的插入和修改权限,无法直接使用提示的配置方式。
相关代码
ConfigPerguntaPk(嵌入式主键)
@Embeddable public class ConfigPerguntaPk { private Long idConfigPergunta; @ManyToOne @JoinColumn(name = "idTipoDoctoEntrada") private TipoDoctoEntrada tipoDoctoEntrada; }
ConfigPergunta(实体类)
@Entity @Table(name = "tbConfigPergunta") @DynamicUpdate public class ConfigPergunta { @EmbeddedId private ConfigPerguntaPk configPerguntaPk; private String txPergunta; private String txAbaDestinoResposta; private String txCelulaDestinoResposta; private Character indAtivo; @ManyToOne @JoinColumn(name = "idUsuarioUltAtualizacao") private Usuario usuarioUltAtualizacao; private LocalDateTime dtHoraInclusao; private LocalDateTime dtHoraUltAtualizacao; @ManyToOne @JoinColumns({ @JoinColumn(name = "idPerguntaClonada" ,referencedColumnName = "idConfigPergunta", insertable = true, updatable = true), @JoinColumn(name = "idTipoDoctoEntrada", referencedColumnName = "idTipoDoctoEntrada", insertable = true, updatable = true) }) private ConfigPergunta configPerguntaClonada; private Character indPerguntaSuperAdmin; }
错误日志
Caused by: jakarta.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.MappingException: Column 'idTipoDoctoEntrada' is duplicated in mapping for entity 'com.provider.fatoria.model.ConfigPergunta' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[spring-orm-6.1.13.jar:6.1.13] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.13.jar:6.1.13] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.1.13.jar:6.1.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-6.1.13.jar:6.1.13] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.1.13.jar:6.1.13] ... 106 common frames omitted Caused by: org.hibernate.MappingException: Column 'idTipoDoctoEntrada' is duplicated in mapping for entity 'com.provider.fatoria.model.ConfigPergunta' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column) at org.hibernate.mapping.Value.checkColumnDuplication(Value.java:196) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.mapping.MappingHelper.checkPropertyColumnDuplication(MappingHelper.java:251) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:939) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:694) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.mapping.RootClass.validate(RootClass.java:276) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:496) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:280) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:457) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506) ~[hibernate-core-6.5.3.Final.jar:6.5.3.Final] at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.13.jar:6.1.13] at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.1.13.jar:6.1.13] at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.13.jar:6.1.13] ... 110 common frames omitted
解决方案
报错原因是idTipoDoctoEntrada字段同时在嵌入式主键和自关联外键中被映射为可插入/更新,导致Hibernate冲突。根据数据库设计的不同,有两种解决方式:
方式一:修正自关联外键字段(推荐)
若数据库表中自关联的外键是独立字段(比如idTipoDoctoEntradaClonada,而非复用当前实体的idTipoDoctoEntrada),修改ConfigPergunta中的自关联映射:
@ManyToOne @JoinColumns({ @JoinColumn(name = "idPerguntaClonada" ,referencedColumnName = "idConfigPergunta", insertable = true, updatable = true), // 将name改为自关联外键的实际字段名 @JoinColumn(name = "idTipoDoctoEntradaClonada", referencedColumnName = "idTipoDoctoEntrada", insertable = true, updatable = true) }) private ConfigPergunta configPerguntaClonada;
方式二:保留现有表结构,调整映射权限
若数据库表确实复用idTipoDoctoEntrada作为自关联外键的一部分,需将自关联映射中的该字段设为只读,通过主键字段控制插入和修改:
@ManyToOne @JoinColumns({ @JoinColumn(name = "idPerguntaClonada" ,referencedColumnName = "idConfigPergunta", insertable = true, updatable = true), // 该字段设为只读,通过configPerguntaPk.tipoDoctoEntrada进行插入/修改 @JoinColumn(name = "idTipoDoctoEntrada", referencedColumnName = "idTipoDoctoEntrada", insertable = false, updatable = false) }) private ConfigPergunta configPerguntaClonada;
此时,idTipoDoctoEntrada的插入和修改操作通过configPerguntaPk.tipoDoctoEntrada属性完成,自关联映射仅用于关联查询,不会影响字段的编辑权限。
内容的提问来源于stack exchange,提问作者Felipe Veiga
相关产品推荐
相关产品推荐

