来自 parent 的 Hibernate OneToMany 错误绑定
Hibernate OneToMany wrong binding from parent
我有一个用 Kotlin 编写的简单 REST spring 启动应用程序。
它有下一个架构:Map
hasOne Channel
和 Channel
hasMany Headers
我只有一个控制器动作,并且想像这样在一个请求中保存我的所有模型:
{
"channel": {
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
如果未设置 header,则所有模型都正确关联并且数据库插入顺序也正确:首先创建 Channel
,然后使用此 Channel
创建 Map
但是当我添加一些 Header
列表时 - Hibernate 在数据库中生成额外的 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(),
...
Header 型号:
...
@JsonIgnore
@ManyToOne(cascade = arrayOf(CascadeType.ALL))
@JoinColumn(name = "channel_id")
var channel: Channel = Channel(),
...
也许应该修复一些注释。很高兴听到任何建议。谢谢大家!
更新
这样保存模型:
@PostMapping("/maps")
fun post(@RequestBody body: Map) = repo.save(body)
更新 2
如果手动创建 object,并将必要的属性类型声明为 nullable
- channel_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
和Header:
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
回答
找到了here
刚刚从集合 属性 中删除 mappedBy = "channel"
并添加 @JoinColumn(name = "channel_id")
我有一个用 Kotlin 编写的简单 REST spring 启动应用程序。
它有下一个架构:Map
hasOne Channel
和 Channel
hasMany Headers
我只有一个控制器动作,并且想像这样在一个请求中保存我的所有模型:
{
"channel": {
"headers": [
{
"name": "Content-Type",
"value": "application/json"
}
]
}
}
如果未设置 header,则所有模型都正确关联并且数据库插入顺序也正确:首先创建 Channel
,然后使用此 Channel
创建 Map
但是当我添加一些 Header
列表时 - Hibernate 在数据库中生成额外的 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(),
...
Header 型号:
...
@JsonIgnore
@ManyToOne(cascade = arrayOf(CascadeType.ALL))
@JoinColumn(name = "channel_id")
var channel: Channel = Channel(),
...
也许应该修复一些注释。很高兴听到任何建议。谢谢大家!
更新
这样保存模型:
@PostMapping("/maps")
fun post(@RequestBody body: Map) = repo.save(body)
更新 2
如果手动创建 object,并将必要的属性类型声明为 nullable
- channel_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
和Header:
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
回答
找到了here
刚刚从集合 属性 中删除 mappedBy = "channel"
并添加 @JoinColumn(name = "channel_id")