Spring JPA,OneToMany 引用部分主键
Spring JPA, OneToMany referencing part of primary key
给定一个 class
@Entity
@Table(name = "ATABLE")
public class A implements Serializable {
public static final String DB_ID = "AID";
public static final String DB_MARKET = "AMARKET";
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = DB_ID)),
@AttributeOverride(name = "market", column = @Column(name = DB_MARKET))
})
public AIdClass id;
@OneToMany
@JoinColumn(name = B.DB_MARKET, referencedColumnName = DB_MARKET, insertable = false, updatable = false)
public List<B> bs;
}
和乙class
@Entity
@Table(name = "BTABLE")
public class B implements Serializable {
public static final String DB_ID = "BID";
public static final String DB_MARKET = "BMARKET";
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = DB_ID)),
@AttributeOverride(name = "market", column = @Column(name = DB_MARKET))
})
public BIdClass id;
}
可能会列出每个实体,但使用 @OneToMany
关系确实会引发以下错误
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory'
Caused by: org.hibernate.AnnotationException: Unable to map collection fr.zzz.domain.A.bs
Caused by: org.hibernate.AnnotationException: referencedColumnNames(AMARKET) of fr.zzz.domain.A.bs referencing fr.zzz.domain.B not mapped to a single property
一个 A
实体与 A.AMARKET = B.BMARKET
上的多个 B
相关
您遇到此问题是因为在对键 AMARKET = BMARKET 进行连接时,组合键 (AID,AMARKET) 和 (BID,BMARKET) 可能不是唯一的。因此,您收到错误 not mapped to a single property
。请耐心等待,使用以下示例数据来分析问题;
对于table一个
AID AMARKET
1 1
2 1
3 2
对于tableB
BID BMARKET
1 1
2 2
3 2
上述情况是绝对可能的(至少在数据库级别)并且仅使用 AMARKET
和 BMARKET
来进行连接 @OneToMany
是不可能的。但是可以使用 @ManyToMany
,如果 table 结构正确,这将立即解决问题。
但是如果由于某些业务限制需要使用 @OneToMany
怎么办?然后您必须更新 table B 以包含 A.AID
并添加外键约束以确保数据完整性。那么只有结果集对关系 @OneToMany
有效。连接将如下所示;
@OneToMany
@JoinColumn(name = B.DB_AID, referencedColumnName = DB_ID)
@JoinColumn(name = B.DB_MARKET, referencedColumnName = DB_MARKET)
public List<B> bs;
在 B 中:
@Entity
@Table(name = "BTABLE")
public class B implements Serializable {
public static final String DB_ID = "BID";
public static final String DB_MARKET = "BMARKET";
public static final String DB_AID = "AID";
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = DB_ID)),
@AttributeOverride(name = "market", column = @Column(name = DB_MARKET))
})
public BIdClass id;
@Column(name = DB_AID)
private Long aid; // assuming aid is a Long
}
现在正在对 A 的复合主键进行连接。
给定一个 class
@Entity
@Table(name = "ATABLE")
public class A implements Serializable {
public static final String DB_ID = "AID";
public static final String DB_MARKET = "AMARKET";
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = DB_ID)),
@AttributeOverride(name = "market", column = @Column(name = DB_MARKET))
})
public AIdClass id;
@OneToMany
@JoinColumn(name = B.DB_MARKET, referencedColumnName = DB_MARKET, insertable = false, updatable = false)
public List<B> bs;
}
和乙class
@Entity
@Table(name = "BTABLE")
public class B implements Serializable {
public static final String DB_ID = "BID";
public static final String DB_MARKET = "BMARKET";
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = DB_ID)),
@AttributeOverride(name = "market", column = @Column(name = DB_MARKET))
})
public BIdClass id;
}
可能会列出每个实体,但使用 @OneToMany
关系确实会引发以下错误
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory'
Caused by: org.hibernate.AnnotationException: Unable to map collection fr.zzz.domain.A.bs
Caused by: org.hibernate.AnnotationException: referencedColumnNames(AMARKET) of fr.zzz.domain.A.bs referencing fr.zzz.domain.B not mapped to a single property
一个 A
实体与 A.AMARKET = B.BMARKET
B
相关
您遇到此问题是因为在对键 AMARKET = BMARKET 进行连接时,组合键 (AID,AMARKET) 和 (BID,BMARKET) 可能不是唯一的。因此,您收到错误 not mapped to a single property
。请耐心等待,使用以下示例数据来分析问题;
对于table一个
AID AMARKET
1 1
2 1
3 2
对于tableB
BID BMARKET
1 1
2 2
3 2
上述情况是绝对可能的(至少在数据库级别)并且仅使用 AMARKET
和 BMARKET
来进行连接 @OneToMany
是不可能的。但是可以使用 @ManyToMany
,如果 table 结构正确,这将立即解决问题。
但是如果由于某些业务限制需要使用 @OneToMany
怎么办?然后您必须更新 table B 以包含 A.AID
并添加外键约束以确保数据完整性。那么只有结果集对关系 @OneToMany
有效。连接将如下所示;
@OneToMany
@JoinColumn(name = B.DB_AID, referencedColumnName = DB_ID)
@JoinColumn(name = B.DB_MARKET, referencedColumnName = DB_MARKET)
public List<B> bs;
在 B 中:
@Entity
@Table(name = "BTABLE")
public class B implements Serializable {
public static final String DB_ID = "BID";
public static final String DB_MARKET = "BMARKET";
public static final String DB_AID = "AID";
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name = "id", column = @Column(name = DB_ID)),
@AttributeOverride(name = "market", column = @Column(name = DB_MARKET))
})
public BIdClass id;
@Column(name = DB_AID)
private Long aid; // assuming aid is a Long
}
现在正在对 A 的复合主键进行连接。