建模含复合键的一对多关系时出现ClassCastException的原因与解决方法
外键属于复合键的一对多关联报错解决
遇到的错误
class org.hibernate.mapping.BasicValue cannot be cast to class org.hibernate.mapping.ToOne
实体类代码
PointInTime 实体
@Entity @Table(name = "point_in_time") class PointInTime( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long, val title: String, val note: String, @OneToMany(mappedBy = "symptom") val symptoms: Set<Symptom> ) { @field:Column(updatable = false) val createdAt: Instant = Instant.now() }
Symptom 实体
@Entity @Table(name = "symptom") @IdClass(SymptomId::class) class Symptom( @ManyToOne(optional = false) @Id @JoinColumn(name = "point_in_time_id", nullable = false) val pointInTime: PointInTime, @Id val category: String, @Id val symptom: String, val strength: Strength )
SymptomId 主键类
class SymptomId ( val pointInTime: Long, val category: String, val symptom: String ): Serializable
异常原因
核心错误是PointInTime类中@OneToMany的mappedBy属性值写错了:你指定的是"symptom",但Symptom实体里关联PointInTime的属性名是pointInTime。
Hibernate解析关联时,发现symptom是Symptom的基础类型主键字段,而非关联对象(ToOne类型),预期的关联映射类型和实际拿到的基础值类型不匹配,因此抛出类型转换异常。
解决方法
修改PointInTime中的@OneToMany注解,将mappedBy的值改为正确的属性名pointInTime:
@Entity @Table(name = "point_in_time") class PointInTime( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long, val title: String, val note: String, // 修正mappedBy的属性名 @OneToMany(mappedBy = "pointInTime") val symptoms: Set<Symptom> ) { @field:Column(updatable = false) val createdAt: Instant = Instant.now() }
另外,SymptomId类的字段名和Symptom实体的主键字段完全匹配,这部分无需修改。
内容的提问来源于stack exchange,提问作者Shade
相关产品推荐
相关产品推荐

