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
相关产品推荐
相关产品推荐

