使用ID的单向@OneToOne
问题描述
我想使用ID创建@OneToOne
单向关系。让我们考虑以下示例:
@Table(name = "user")
@Entity
class User (
@Id
@GeneratedValue(...)
var id: Long? = null,
@OneToOne
var address: UserAddress? = null
)
@Table(name = "user_address")
@Entity
class UserAddress(
@Id
var id: Long? = null,
(...)
)
在数据库上,user_address.id
上有引用user.id
的外键约束。我尝试使用许多不同的注释组合,但是删除仍然存在问题。我正在使用User的JpaRepository,并且当调用userRepository.deleteById(id)
时,仅删除了子级(address
),而不删除了父级(user
)。我真的想保留名称为“ id”的@Id
列。可能吗?
编辑
当我使用以下代码时:
@Table(name = "user")
@Entity
class User (
@Id
@GeneratedValue(...)
var id: Long? = null,
@OneToOne(cascade = [CascadeType.All])
@JoinColumn(name = "id", referencedColumnName = "id")
var address: UserAddress? = null
)
@Table(name = "user_address")
@Entity
class UserAddress(
@Id
var id: Long? = null,
@OneToOne(mappedBy = "address")
var user: User? = null
(...)
)
[调用userRepository.deleteById(id)
时,仅删除子项。我不知道为什么。此外,我想保持这种关系是单向的。
思路一:
您需要的是级联删除,可以通过将orphanRemoval=true
传递到@OneToOne
批注来实现。
示例:
@OneToOne(orphanRemoval=true)
var address: UserAddress? = null
或者,您也可以使用cascade=CascadeType.REMOVE
代替orphanremoval=true
。
从ObjectDB借来:
如果指定了
orphanRemoval=true
,则断开连接的地址实例被自动删除。这对于清理依赖项很有用没有来自的引用就不应该存在的对象(例如地址)所有者对象(例如Employee)。如果只有cascade=CascadeType.REMOVE
由于断开了与关系不是删除操作。
希望这会有所帮助!
思路二:
[我有一个类似的问题要解决时,遵循的一个很好的教程:https://www.baeldung.com/jpa-one-to-one。该教程使用Java,但是我认为您可以轻松地针对Kotlin进行调整。
您的示例缺少什么:
- 对于
User
类,您需要定义@JoinColumn
批注。另外,您需要定义cascade
属性。 - 对于您的
UserAddress
类,您需要向用户添加关系映射:mappedBy
- 此外,如果要将列的名称保持为
id
,只需添加@Column(name = "id")
批注。
这是适合您的情况的调整后的示例:
@Table(name = "user")
@Entity
class User (
@Id
@GeneratedValue(...)
var id: Long? = null,
// added cascade and JoinColumn
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "user_address_id", referencedColumnName = "id")
var address: UserAddress? = null
)
@Table(name = "user_address")
@Entity
public class UserAddress {
@Id
@GeneratedValue(...)
@Column(name = "id")
var id: Long? = null,
// added this field
@OneToOne(mappedBy = "user_address")
var user: User? = null,
(...)
}
编辑:我已经快速创建了一个Spring Boot项目,该项目具有此关系映射的有效示例:https://github.com/alexsomai/spring-boot-one-to-one。它在内存数据库中使用H2,所以我知道这不是理想的解决方案。也许您可以将其用作代码的起点。
思路三:
各种问题。
映射是错误的方法。
@JoinColumn
需要在另一侧,即FK。您实际上是在说地址依赖于(具有FK)地址时,您所使用的定义方式。您已经在从属实体上重新定义了
@Id
字段,即使它是从User
实体中获取其ID的。您需要删除它并在此处通过用@Id
注释关系来表明它是共享的主键关系。
用户:
@Table(name = "user")
@Entity
class User (
@Id
@GeneratedValue(...)
var id: Long? = null,
@OneToOne(cascade = [CascadeType.All], mappedBy="user")
var address: UserAddress? = null
)
地址:
@Table(name = "user_address")
@Entity
class UserAddress(
@Id
@OneToOne
@JoinColumn(name = "id", referencedColumnName = "id")
var user: User? = null
(...)
)