Spring JPA多对一关联重复列映射报错及解决方案咨询
报错信息
Column 'transactionNumber' is duplicated in mapping for entity 'com.myproject.Entities.IndividualItemsTransactionEntity' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
问题原因
在IndividualItemsTransactionEntity中,transactionNumber数据库列被重复映射了两次:
- 一次通过
@Column注解直接绑定到类的transactionNumber字段 - 另一次通过
@ManyToOne的@JoinColumn注解,在关联TransactionsEntity时又绑定了同一个列
Hibernate不允许同一数据库列被实体类的多个属性重复映射,除非明确指定该字段不参与插入、更新操作。
解决方案
方案一:保留transactionNumber字段,添加约束注解
修改IndividualItemsTransactionEntity中的transactionNumber字段注解,明确该字段不参与插入和更新,让关联的TransactionsEntity维护外键:
@Entity @Table(name = "individual_items_transaction") @Getter @Setter @Builder @Data @AllArgsConstructor @NoArgsConstructor public class IndividualItemsTransactionEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "individualItemTransactionID", columnDefinition = "bigint", insertable=false, updatable=false) private Long individualItemTransactionID; // 添加insertable=false, updatable=false避免映射冲突 @Column(name = "transactionNumber", columnDefinition = "varchar(12)", length = 12, nullable = false, insertable=false, updatable=false) private String transactionNumber; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "transactionNumber", nullable = false) TransactionsEntity transactionsEntity; }
方案二:移除单独的transactionNumber字段(更规范)
直接删除IndividualItemsTransactionEntity中的transactionNumber字段,通过关联的transactionsEntity对象获取交易编号,彻底避免重复映射:
@Entity @Table(name = "individual_items_transaction") @Getter @Setter @Builder @Data @AllArgsConstructor @NoArgsConstructor public class IndividualItemsTransactionEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "individualItemTransactionID", columnDefinition = "bigint", insertable=false, updatable=false) private Long individualItemTransactionID; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "transactionNumber", nullable = false) TransactionsEntity transactionsEntity; // 可选:添加快捷方法获取交易编号 public String getTransactionNumber() { return transactionsEntity != null ? transactionsEntity.getTransactionNumber() : null; } }
额外优化:规范双向关联映射
在TransactionsEntity的@OneToMany注解中添加mappedBy属性,指定由多的一方(IndividualItemsTransactionEntity的transactionsEntity)维护关联关系,避免Hibernate生成额外中间表:
@Entity @Table(name = "transactions") @Builder @AllArgsConstructor @NoArgsConstructor @Data public class TransactionsEntity { @Id @NonNull @Column(name = "transactionNumber", columnDefinition = "varchar(12)", length = 12) private String transactionNumber; // 使用mappedBy指定关联维护方 @OneToMany(fetch = FetchType.LAZY, mappedBy = "transactionsEntity") List<IndividualItemsTransactionEntity> individualItemsTransactionEntities; // 其他字段... }
内容的提问来源于stack exchange,提问作者Jason Chan

