Hibernate OneToMany从父节点绑定错误

我有一个简单的REST弹簧启动应用程序写在Kotlin上。

它有下一个模式: Map hasOne ChannelChannel hasMany Headers

我只有一个控制器的动作,并希望将所有模型保存在一个请求中,如下所示:

 { "channel": { "headers": [ { "name": "Content-Type", "value": "application/json" } ] } } 

如果未设置标题,则所有模型都正确关联,并且数据库插入顺序也是正确的:先创建Channel ,然后使用此Channel创建一个Map

但是,当我添加一些Header列表 – 休眠使数据库中的额外Channel (ID = 2)行,并绑定所有Header模型到此通道(ID = 2)

地图模型:

 ... @ManyToOne(cascade = arrayOf(CascadeType.ALL)) @JoinColumn(name = "channel_id") var channel: Channel = Channel(), ... 

频道模式:

 ... @OneToMany(mappedBy = "channel", cascade = arrayOf(CascadeType.ALL), ) var headers: MutableSet<Header> = mutableSetOf(), ... @JsonIgnore @OneToMany(mappedBy = "channel", cascade = arrayOf(CascadeType.ALL)) var maps: MutableSet<Map> = mutableSetOf(), ... 

标题模型:

 ... @JsonIgnore @ManyToOne(cascade = arrayOf(CascadeType.ALL)) @JoinColumn(name = "channel_id") var channel: Channel = Channel(), ... 

也许一些注解应该是固定的。 很高兴听到任何建议。 感谢所有!

UPDATE

保存这样的模型:

 @PostMapping("/maps") fun post(@RequestBody body: Map) = repo.save(body) 

更新2

如果手动创建对象,并将必要的属性类型声明为nullablechannel_id将为null

添加此代码的行动

 val channel = Channel( ... ) body.channel!!.headers.forEach { val header = Header( name = it.name, value = it.value ) channel.headers.add(header) } val map = Map( channel = channel ) return repo.save(map) 

我想这是因为在你的Header ,每创建一个Header实例,你都要创建一个新的Channel 。 而且,您将CascadeType设置为ALL ,这意味着此新创建的Channel也被保留。

您可以在Header设置Channel?类型为Channel? 然后设置各自的channel

编辑要回答来自评论的问题: channel_id将在您分配相应channel并保存此Header后自动设置。

编辑2首先,我建议编辑模型:

地图:

 var channel: Channel? = null 

和标题:

 var channel: Channel? = null 

相关部分的代码:

 val channel = ... // your Channel entity that is already persisted, for example map.channel (if map was saved before) val header = Header(..., channel, ...) // create a new Header and set the channel channel.headers.add(header) // it's bidirectional repo.save(channel) // this should be enough as you have CascadeType.ALL set, so header should be persisted automatically 

回答

它在这里找到了

刚从集合属性中移除mappedBy = "channel" ,并添加@JoinColumn(name = "channel_id")