You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA/Hibernate中如何用Reader主键与Book主键关联复合键实体Reading?

可行性分析与实现方案

完全可行。因为Reading的复合主键由reader_id和book_id共同组成,对于任意一个Reader实例,只要确定对应的book_id,就能唯一匹配到一条Reading记录(每个读者和书籍的组合是唯一的)。以下是具体实现步骤:

1. 修正Reading的复合主键类

原代码中Reading.Id使用实体类型作为字段,不符合JPA对复合主键类的要求(主键类字段需与实体中@Id属性的类型一致),需修改为对应主键的基础类型:

@Entity
@IdClass(Reading.Id::class)
class Reading(
    @Id
    @ManyToOne
    val book: Book,

    @Id
    @ManyToOne
    val reader: Reader
) {
    // 改为使用主键类型Long,与Book、Reader的ID类型匹配
    data class Id(val book: Long, val reader: Long) : Serializable

    var comment: String = ""
}

2. 修改Reader实体实现关联

在Reader中添加存储最佳阅读书籍ID的字段,通过@OneToOne结合@JoinColumns指定关联条件,将当前Reader的ID和存储的书籍ID与Reading的复合主键关联:

@Entity
class Reader {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    var id: Long? = null

    @OneToMany(mappedBy = "reader")
    val readings = mutableListOf<Reading>()

    // 存储最佳阅读对应的书籍ID,用于关联Reading
    var bestBookId: Long? = null

    // 关联Reading:通过当前Reader的ID匹配Reading的reader_id,通过bestBookId匹配Reading的book_id
    @OneToOne
    @JoinColumns(
        JoinColumn(name = "id", referencedColumnName = "reader_id", insertable = false, updatable = false),
        JoinColumn(name = "best_book_id", referencedColumnName = "book_id", insertable = false, updatable = false)
    )
    var bestReading: Reading? = null
}

关键注意事项

  • @JoinColumns中的insertable = false, updatable = false表示bestReading关联由bestBookId维护,不能直接通过修改bestReading来更新关联,需通过修改bestBookId的值切换最佳阅读记录。
  • 确保数据库表中Reading表的复合主键字段(默认book_id、reader_id)与@JoinColumns中指定的referencedColumnName一致,若自定义了列名需同步调整。

内容的提问来源于stack exchange,提问作者Javaddict

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.01 13:04:56