使用Spring Boot/Hibernate关联Users、Technologies、Categories三张表咨询
问题根源分析
你当前的实现存在3个核心错误:
- 关联关系映射错误:
UserCategory中未关联TechnologyCategory实体,仅存储分类名称,无法复用已存在的分类数据 - 级联策略配置不合理:未限制关联操作的级联范围,导致保存用户关联时触发分类的新增逻辑
- 实体关联方向错误:
MyUser中直接关联Category而非中间关联实体UserCategory,mappedBy配置错误导致外键关联失效,进而触发Hibernate建表异常
修正后的实体代码
1. TechnologyCategory(技术分类实体)
增加唯一约束避免分类名称重复,无需配置反向关联
@Entity public class TechnologyCategory { @Id @SequenceGenerator(name = "id_seq", sequenceName = "id_seq", allocationSize = 1, initialValue = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_seq") private int id; @Column(name="name", unique = true, nullable = false) private String name; // 省略getter/setter }
2. Technology(技术实体)
保持原有基础配置即可,可根据需要添加和UserCategory的反向关联
@Entity public class Technology { @Id @SequenceGenerator(name = "id_seq", sequenceName = "id_seq", allocationSize = 1, initialValue = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_seq") private int id; @Column(name = "name", unique = true, nullable = false) private String name; // 省略getter/setter }
3. UserCategory(用户-分类关联实体)
替换原有分类名称字段为TechnologyCategory实体关联,新增和MyUser的关联,配置合理的级联规则
@Entity public class UserCategory { @Id @SequenceGenerator(name = "id_seq", sequenceName = "id_seq", allocationSize = 1, initialValue = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_seq") private int id; // 关联已有分类实体,不配置级联新增/更新,避免生成重复分类 @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "category_id", referencedColumnName = "id") private TechnologyCategory category; // 关联所属用户 @ManyToOne(fetch = FetchType.LAZY, optional = false) @JoinColumn(name = "user_id", referencedColumnName = "id") private MyUser myUser; // 关联技术列表,配置多对多中间表 @ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinTable( name = "user_category_technology", joinColumns = @JoinColumn(name = "user_category_id"), inverseJoinColumns = @JoinColumn(name = "technology_id") ) private Collection<Technology> technologies; // 省略getter/setter }
4. MyUser(用户实体)
修改关联字段为UserCategory,配置正确的mappedBy属性
@Entity public class MyUser { @Id @SequenceGenerator(name = "id_seq", sequenceName = "id_seq", allocationSize = 1, initialValue = 1) @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_seq") private int id; // 其他用户属性 // 关联用户对应的分类绑定关系 @OneToMany(mappedBy = "myUser", cascade = CascadeType.ALL, orphanRemoval = true) private Collection<UserCategory> userCategories; // 省略getter/setter }
业务层实现注意事项
- 系统初始化阶段提前将10个固定分类存入
TechnologyCategory表,后续所有分类关联均复用这10条已有数据 - 给用户创建分类关联时,必须先通过ID/名称从数据库查询已存在的
TechnologyCategory对象,再关联到UserCategory,禁止直接new新的TechnologyCategory对象保存 - 如果技术也需要全局复用,保存技术时同样要先查询数据库是否存在对应记录,存在则复用,不存在再新增
内容的提问来源于stack exchange,提问作者NolanB
相关产品推荐
相关产品推荐

