spring-boot - Hibernate OneToMany 来自父级的错误绑定(bind)

标签 spring-boot kotlin hibernate-onetomany

我有一个用 Kotlin 编写的简单的 REST spring boot 应用程序。

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

我只有一个 Controller 操作,并且希望将所有模型保存在一个请求中,如下所示:

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

如果未设置 header ,则所有模型都正确关联,并且数据库插入顺序也正确:首先创建 Channel,然后使用此 Channel< 创建 Map/

但是当我添加一些 Header 列表时 - Hibernate 在数据库中创建额外的 Channel (ID=2)行并绑定(bind)所有 此 channel 的标题模型(ID = 2)

map 模型:

...
@ManyToOne(cascade = arrayOf(CascadeType.ALL))
@JoinColumn(name = "channel_id")
var channel: 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(),
...

也许应该修复一些注释。将很高兴听到任何建议。谢谢大家!

更新

像这样保存模型:

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

更新2

如果手动创建对象,并将必要的属性类型声明为 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 并保存此标题后,将自动设置channel_id

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

map :

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

关于spring-boot - Hibernate OneToMany 来自父级的错误绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46068169/

相关文章:

java - Spring Boot application.yml 和 application.properties

Ajax Thymeleaf Springboot

java - 等待最后一个元素时阻塞 Flux

java - 如何使用jpaRepository的deleteInBatch方法获取已删除行的记录数

kotlin - Gradle Kotlin DSL Jar.from() 的使用

java - Android Kotlin/JAVA - 获取自 1970 年以来的当前世界时间/UTC(以秒为单位)

java - Hibernate 是否可以通过一次选择获取两层集合?

java - JPA (Hibernate) 上的多个双向映射问题

java - Hibernate:如何编写 HQL 来获取没有其标识关系记录的实体的记录

java - 如何在 spring boot 中连接到 MongoDB?