Hibernate集合映射自动生成外键问题:关联外键未正确写入
搞定Hibernate双向关联外键不写入的问题
嘿,你的问题我太熟了,这是新手用Hibernate双向关联时最容易踩的两个坑,咱们来一步步捋清楚:
1. 第一个致命坑:注解把外键锁死了
看你更新1里的Message类的@JoinColumn配置:
@ManyToOne @JoinColumn(name = "conversation_id", insertable = false, updatable = false) private Conversation conversation;
你把insertable和updatable设成false,等于直接告诉Hibernate:“这个字段你别碰,我自己来管”——但你根本没手动赋值啊!Hibernate自然就跳过了这个外键的写入,日志里看不到conversation_id完全是预期结果。
马上修正:删掉这两个多余的属性
把Message的关联注解改成这样就好:
@ManyToOne @JoinColumn(name = "conversation_id") // 只保留外键名称,其他默认即可 private Conversation conversation;
2. 第二个坑:双向关联的一致性没维护好
Hibernate不会自动帮你同步双向关联的两端,说白了就是:
- 你往Conversation的messages集合里加Message的时候,必须同时给Message设置对应的Conversation引用
- 反过来,给Message设置Conversation的时候,最好也把Message加到Conversation的集合里(不过因为你开了
cascade = CascadeType.PERSIST,前者更关键)
你更新2里的代码其实已经做了setConversation(conversation),这部分是对的,但为了以后不踩忘写的坑,建议在Conversation里加个工具方法来自动维护关联:
@Entity public class Conversation{ // ... 其他字段和getter/setter @OneToMany(mappedBy = "conversation", cascade = CascadeType.PERSIST) private Set<Message> messages = new HashSet<Message>(); // 加这个方法,以后添加消息就用它 public void addMessage(Message message) { messages.add(message); message.setConversation(this); // 自动同步Message的关联 } }
之后调用的时候就简单多了,也不会漏写:
Conversation conversation = new Conversation(); Message message = new Message(); message.setText("test"); conversation.addMessage(message); // 一步搞定双向关联 session.persist(conversation);
最后再检查两个小点
- 确保你的数据库里,
conversation_message表的conversation_id字段是允许非空的(外键一般都要加非空约束) - 确认Conversation表的主键是自增类型(比如MySQL的AUTO_INCREMENT),和你用的
GenerationType.IDENTITY匹配
修正完之后,你再看Hibernate的日志,应该就能看到insert into conversation_message语句里带上conversation_id了,问题就解决啦!
内容的提问来源于stack exchange,提问作者bohemak2
相关产品推荐
相关产品推荐

