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

上述情况是绝对可能的(至少在数据库级别)并且仅使用 AMARKETBMARKET 来进行连接 @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 的复合主键进行连接。