【问题标题】:Reference to another object when reading but save with ID only读取时引用另一个对象但仅使用 ID 保存
【发布时间】:2020-07-05 11:32:35
【问题描述】:

我有一对多的关系,如下所述:

@Entity
@Table(name = "some")
data class SomeEntity(
    val otherId: UUID,

    @Column(nullable = false)
    val number: String = "12345",
) {
    @Id
    @Column(updatable = false, nullable = false, unique = true)
    val id: UUID = UUID.randomUUID()
}

@Entity
@Table(name = "other")
data class OtherEntity(
    @Id
    @Column(updatable = false, nullable = false)
    val id: UUID = UUID.randomUUID(),
)

我不需要指定它们是@OneToMany 还是@JoinColumn 注释。

通过这个结构,我可以保存一个新的OtherEntity,然后我可以通过传递之前返回的id来保存一个新的SomeEntity

val ent1 = OtherEntity()
val savedEnt1 = otherRepository.save(ent1)

val ent2 = SomeEntity(savedEnt1.id, "123")
val savedEnt2 = someRepository.save(ent2)

我想要实现的是能够从 SomeEntity 对象中检索 OtherEntity 对象。

val other: OtherEntity = ent2.other

如果我只是在构造函数中添加整个实体,则每次要保存一个新的SomeEntity时都必须传递整个SomeEntity

如何在构造函数中不包含 OtherEntity 的引用?

【问题讨论】:

    标签: hibernate spring-boot kotlin spring-data-jpa


    【解决方案1】:

    您想要实现的目标是挑战 JPA 背后的理念。即封装持久性数据库存储层并将其隐藏,以便您可以使用 JVM 对象,而无需反映应如何组织它们的数据以使其在关系数据库中有意义。

    您可能知道,@Entity 是 JPA 的基本概念之一。通过实现和注释一个@Entity 对另一个的引用,您可以让 JPA 了解它必须提前准备哪些 SQL 语句以用于您的数据库查询,以及它应该对表和列实施哪些约束。这不能基于一个有缺陷的简单假设来计算,即字段 xyzId 显然必须是对实体的 Xyz 主键的引用。

    此外,您想要直接实现的代码指出您希望您的SomeEntity 类有一个字段other: OtherEntity,而不是otherId: UUID。但是由于一个实体必须存储在另一个表中,根据 RDMS 的原则,这就是首先使用 JPA 的原因 - 进行繁重的工作,即让一个字段将外键存储到另一个存储在一个模型,以便所述键可用于手动从另一个表中检索数据。

    退后一步,重新评估您的假设。请记住,在 @Entity 类之间定义关系并不一定意味着不断过度获取数据 - 因为如果需要,这些相关实体可能会按需延迟加载。

    【讨论】:

    • 我可能在我的示例中犯了一些错误,但我之前在另一个使用 Java 的项目中做过。基本上,我想要实现的是在创建新的父实体时不需要始终引用整个实体。假设我只使用 sql:insert into other(id, other_column) values ('other_id', 'column_value');insert into some(id, other_id, number) values('some_id', 'other_id', '12345'); 在第二个查询中,other 实体的 ID 是创建 some 实体所需的唯一信息。
    • 是的,我确实意识到将这种关系引入数据库需要什么 SQL 语句。此外,我向您保证,这是 JPA 最终将用来存储这种关系的那种语句,因为它是一个框架,旨在转换面向对象的运行时环境,其中对象直接引用其他对象*到引用的 SQL 环境由其他表的故事键保存。我可以帮助您启用 SQL 调试,这样您就可以看到 JPA 实际为您做了什么。不要为它做它的工作。 *在机器级别上不正确,但这是一个常识抽象
    猜你喜欢
    • 2018-11-25
    • 2016-05-07
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2020-05-24
    相关资源
    最近更新 更多