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

Hibernate双向ManyToMany映射DDL异常求助

解决User与EmployeeRole双向ManyToMany映射的DDL异常问题

嘿,我来帮你排查这个问题!从错误日志来看,核心问题是MySQL的外键约束创建失败(errno:150),咱们一步步来分析和修复。

问题回顾

你有User、Role、EmployeeRole和AccessPermission四个实体,在配置User与EmployeeRole的双向ManyToMany映射(User作为关联所有者)时,运行代码抛出了DDL执行异常。

相关实体代码

User实体

@Entity @Table(name="user")
public class User{
    @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idgenerator")
    @SequenceGenerator(initialValue = 1, name = "idgenerator", sequenceName = "usersSeq")
    private long id;
    @Column(name="company_id") private String companyId;
    @Column(name = "password") private String password;
    @Column(name= "firstname") private String firstName;
    @Column(name = "lastname") private String lastName;
    @Column(name = "email") private String email;
    @Column(name = "active") private int active;
    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "user_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    private Set<Role> roles;
    @ManyToMany(cascade = CascadeType.PERSIST)
    @JoinTable(name = "user_has_role", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "emp_role_id"))
    private Set<EmployeeRole> empRoles = new HashSet<>();
    // getters and setters.
}

EmployeeRole实体

@Entity @Table(name="employeeRole")
public class EmployeeRole extends AbstractData {
    @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idgenerator")
    @SequenceGenerator(initialValue = 1, name = "idgenerator", sequenceName = "employeeRoleSeq")
    @Column(name = "id", updatable = false, nullable = false)
    private long id;
    @NotBlank @Size(min = 1, max = 255)
    @Column(name="roleName") protected String roleName;
    @Column(name="roleDescription") protected String roleDescription;
    @ManyToMany(mappedBy="empRoles")
    private Set<User> user = new HashSet<>();
    // getters and setters.
}

错误日志

alter table user_has_role add constraint FKdtkvc2iy3ph1rkvd67yl2t13m foreign key (user_id) references user (id)
2019-07-19 14:05:38.758 WARN 11756 --- [ main] o.h.t.s.i.ExceptionHandlerLoggedImpl : GenerationTarget encountered exception accepting command : Error executing DDL " alter table user_has_role add constraint FKdtkvc2iy3ph1rkvd67yl2t13m foreign key (user_id) references user (id)" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL " alter table user_has_role add constraint FKdtkvc2iy3ph1rkvd67yl2t13m foreign key (user_id) references user (id)" via JDBC Statement
    at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
    ...
Caused by: java.sql.SQLException: Can't create table `possystem`.`#sql-4a0_17c` (errno: 150 "Foreign key constraint is incorrectly formed")
    ...

问题原因分析

这个错误的核心原因是你把User实体的表名设为了user,而user是MySQL的保留关键字。当Hibernate尝试生成外键约束引用user表时,MySQL会把它当成关键字解析,导致SQL语法错误,最终外键约束创建失败。

解决方案

1. 修改User实体的表名,规避保留关键字

把User实体上的@Table(name="user")改成非保留字的名称,比如users或者app_user,这样就能避免MySQL的语法解析冲突。

修改后的User实体开头代码:

@Entity @Table(name="users") // 替换原有的"user"表名
public class User{
    @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "idgenerator")
    @SequenceGenerator(initialValue = 1, name = "idgenerator", sequenceName = "usersSeq")
    private long id;
    // 其余字段和关联关系保持不变
}

2. 清理并重新生成表结构(可选,针对已有错误表的情况)

如果你的数据库中已经生成了错误的表结构,建议先删除user、user_has_role这些相关表,或者在Hibernate配置中设置hibernate.hbm2ddl.auto=create(仅测试环境使用),让Hibernate重新生成正确的表和外键约束。

3. 优化EmployeeRole的集合命名(代码可读性提升)

EmployeeRole中的集合字段user语义上是多个用户,建议改成users,让代码更易读:

@ManyToMany(mappedBy="empRoles")
private Set<User> users = new HashSet<>(); // 把user改为users

验证修复

完成以上修改后,重新运行你的应用,Hibernate应该能顺利生成所有表和外键约束,不会再出现errno:150的异常了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:17:53