类似于 @ManyToOne 在 JPA 中引用复合键。这是使用 Hibernate 5.6 的旧版本 Spring Boot。
我有三个实体类:
@Entity class A { Long getId(); ... }
@Entity class B { Long getId(); ... }
@Entity
@IdClass(ABPK.class)
@Data
class AB {
@Id
@Column(name="a_id", insertable=false, updatable=false)
private Long aId;
@Id
@Column(name="b_id", insertable=false, updatable=false)
private Long bId;
@ManyToOne
@JoinColumn(name="a_id")
private A a;
@ManyToOne
@JoinColumn(name="b_id")
private B b;
public AB() { }
public AB(A a, B b) {
this.a = a;
this.aId = a.getId();
this.b = b;
this.bId = b.getId();
}
}
@Data
class ABPK implements Serializable {
Long aId;
Long bId;
}
当我尝试创建并保存它时
var a = new A("a");
var b = new B("b");
var ab = new AB(a,b);
abDao.saveAndFlush(ab);
我遇到了最奇怪的错误
原因:java.sql.SQLException:参数索引超出范围(3 > 参数数量,即 2)。
它生成的插入语句在日志中是正确的
Hibernate: insert into ab (a_id, b_id) values (?, ?)
我运行了调试器,当我只期待两个时,它似乎添加了第三个“字段”来映射,第一个似乎是
AB
类型,然后是 A
,然后是 B
。
我用 Hibernate 5.6.15 重现了这个问题 - 尽管确切的版本并不重要,但我认为这是规范中的一个复杂区域,其细节通常被误解。无论如何,关系字段中的
@MapsId
为我解决了问题。即:
@Entity
@IdClass(ABPK.class)
@Data
class AB {
@Id
@Column(name="a_id", insertable=false, updatable=false)
private Long aId;
@Id
@Column(name="b_id", insertable=false, updatable=false)
private Long bId;
@MapsId("aId") // <--- HERE
@ManyToOne
@JoinColumn(name="a_id")
private A a;
@MapsId("bId") // <--- AND HERE
@ManyToOne
@JoinColumn(name="b_id")
private B b;
public AB() { }
public AB(A a, B b) {
this.a = a;
this.aId = a.getId();
this.b = b;
this.bId = b.getId();
}
}