Hibernate3迁移Hibernate5复合主键出现重复映射报错问题求解
解决方案
你遇到的是Hibernate 5对重复字段映射校验逻辑收紧,加上类加载顺序不稳定导致的偶发报错,可按以下步骤修复:
- 移除冗余的映射配置
primary-hibernate.cfg.xml中不需要单独声明@Embeddable注解的复合主键类映射,仅保留主实体映射即可:
<mapping class="com.ekotrope.server.model.user.UserRole" />
删除<mapping class="com.ekotrope.server.model.user.UserRolePK" />这行配置,重复映射会加剧类加载时的校验冲突概率。
2. 删除主实体类中重复的字段映射UserRole类中不需要单独定义role字段,该字段已经在复合主键UserRolePK中定义,如需直接获取role值,新增委托方法即可,不需要重复映射数据库列。
3. 用@MapsId注解绑定关联字段与复合主键的对应关系
针对User关联字段使用@MapsId明确关联的是复合主键中的userId属性,避免Hibernate判定为两个独立的字段映射:
修改后的UserRole类核心代码如下:
@Entity @Table(name="roles") public class UserRole implements Serializable { @EmbeddedId private UserRolePK userRolePK; @ManyToOne(fetch = FetchType.LAZY) @MapsId("userId") @JoinColumn(name = "userId", insertable=false, updatable=false) private User user; // 新增委托方法直接获取role,无需重复映射 public Role getRole() { return userRolePK.getRole(); } // 剩余getters/setters/equals/hashcode/toString保留原有逻辑即可 }
- **可选优化:移除复合主键类中多余的只读属性
UserRolePK类里的insertable=false, updatable=false配置可以直接删除,@MapsId会自动同步关联字段的读写状态到复合主键对应的属性上,不会产生写入冲突。
报错说明
报错中提到的insert="false" update="false"是Hibernate的提示字符串未更新,实际对应的就是你代码里的insertable和updatable属性,无需纠结属性名差异,本质是检测到同一数据库列被多次映射。
偶发生效的原因是Hibernate 5的类加载顺序不固定,当类加载顺序刚好绕开重复映射校验逻辑时就能正常运行,项目重建后加载顺序变化就触发报错,属于可复现的必然问题。
内容的提问来源于stack exchange,提问作者tjholmes66
相关产品推荐
相关产品推荐

