Hibernate OneToOne关联JoinTable时出现MappingException问题求助
问题分析与解决方案
原错误org.hibernate.MappingException: broken column mapping for: agencyManager.id of: org.tuto.persistence.entity.Agency的核心原因是JPA映射配置错误,主要包括以下几点:
- 中间表实体
AgencyManager的关联字段注解写反 - 嵌入式主键
AgencyManagerPK错误地使用实体关联替代基本类型字段 - 主实体
Agency/Employee的mappedBy属性指向错误
以下是修正后的完整映射方案,完全满足你单独持久化Agency/Employee、获取关联关系的需求,同时兼容你期望的操作代码:
1. 修正嵌入式主键类 AgencyManagerPK
嵌入式主键需映射数据库主键列的基本类型,而非直接关联实体:
@Embeddable @Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode public class AgencyManagerPK implements Serializable { @Serial private static final long serialVersionUID = 7474913724940112916L; @Column(name = "employee_id") private Long employeeId; @Column(name = "agency_id") private Long agencyId; }
2. 修正中间表实体 AgencyManager
使用@MapsId关联嵌入式主键字段,同时修正关联关系的方向:
@Entity @Table(name = "agency_manager") @Data @Builder @NoArgsConstructor @AllArgsConstructor public class AgencyManager { @EmbeddedId private AgencyManagerPK id; @OneToOne @MapsId("employeeId") @JoinColumn(name = "employee_id") private Employee manager; @OneToOne @MapsId("agencyId") @JoinColumn(name = "agency_id") private Agency agency; }
3. 修正机构实体 Agency
调整mappedBy指向AgencyManager中的agency字段:
@Entity @Table(name = "agency") @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Agency { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String reference; private Integer numberOfEmployee; private Calendar creationDate; @OneToOne(mappedBy = "agency", fetch = FetchType.LAZY) private AgencyManager agencyManager; }
4. 修正员工实体 Employee
调整mappedBy指向AgencyManager中的manager字段,同时修正字段命名规范:
@Entity @Table(name = "employee") @Data @Builder @NoArgsConstructor @AllArgsConstructor public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String firstName; private Gender gender; private Calendar birthDate; private String socialSecurityNumber; @OneToOne(mappedBy = "manager", fetch = FetchType.LAZY) private AgencyManager managedAgency; public boolean isAgencyManager(){ return managedAgency != null; } }
5. 验证操作代码
修正后的代码可直接运行你期望的持久化逻辑(无需手动构建主键对象,简化代码):
Employee employee=Employee.builder() .name("Simple") .firstName("Employee") .socialSecurityNumber("112345") .gender(Gender.MALE) .build(); Agency agency = Agency.builder() .reference("ONLY8976GYT7") .numberOfEmployee(39) .build(); EntityManager em = JpaUtils.getEmF().createEntityManager(); em.getTransaction().begin(); em.persist(agency); em.persist(employee); AgencyManager agencyManager = AgencyManager.builder() .manager(employee) .agency(agency) .build(); employee.setManagedAgency(agencyManager); agency.setAgencyManager(agencyManager); em.persist(agencyManager); em.getTransaction().commit();
关键说明
- 所有实体需包含无参构造器(Lombok的
@NoArgsConstructor自动生成) - 嵌入式主键必须重写
equals和hashCode(Lombok的@EqualsAndHashCode自动生成) - 使用
fetch = FetchType.LAZY可优化关联加载性能,避免不必要的数据库查询 - 修正后的映射完全支持单独持久化
Agency/Employee,后续再建立经理关联
内容的提问来源于stack exchange,提问作者TheoMalo2021
相关产品推荐
相关产品推荐

