You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单表继承关联问题:Hibernate映射code_list表报错求解决方案

Fixing Hibernate's Composite Primary Key Mismatch in Single-Table Inheritance

I’ve run into this exact issue before when working with composite primary keys in Hibernate single-table inheritance—let’s break down what’s going wrong and how to fix it.

What’s Causing the Error?

The error message says it all: your code_list table uses a composite primary key (val_string + id_code_list), but your @ManyToOne association in the Affiliate entity only maps to one column (typ_aff). Hibernate can’t create a valid foreign key because the number of columns doesn’t match the referenced primary key.

The @Where annotation won’t help here—it only filters query results, it doesn’t adjust the underlying entity mapping or foreign key structure.

Step-by-Step Solution

1. Define the Composite Primary Key Class

First, create an embeddable class to represent the composite key of code_list. This is required for Hibernate to properly map the two-column primary key:

@Embeddable
public class CodeListId implements Serializable {
    @Column(name = "val_string")
    private String value;
    
    @Column(name = "id_code_list")
    private String typeCode;
    
    // Hibernate requires a no-arg constructor
    public CodeListId() {}
    
    // Convenience constructor to set both key fields
    public CodeListId(String value, String typeCode) {
        this.value = value;
        this.typeCode = typeCode;
    }
    
    // Getters and setters
    
    // Critical: Implement equals() and hashCode() based on both fields
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        CodeListId that = (CodeListId) o;
        return Objects.equals(value, that.value) && Objects.equals(typeCode, that.typeCode);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(value, typeCode);
    }
}

2. Update the Abstract Parent Class

Modify your CodeListString class to use the composite key and properly link the discriminator column (which is part of the primary key):

@Entity
@Table(name = "code_list")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "id_code_list", discriminatorType = DiscriminatorType.STRING)
public abstract class CodeListString {
    @EmbeddedId
    private CodeListId id;
    
    // Add shared fields or methods here (if any)
    
    // Getters and setters
}

3. Configure the AffiliateType Subclass

The subclass’s discriminator value maps directly to the typeCode part of the composite key. We can enforce this with a convenience constructor:

@Entity
@DiscriminatorValue("TYP_AFF")
public class AffiliateType extends CodeListString {
    // Add subclass-specific fields (if any)
    
    // No-arg constructor required by Hibernate
    protected AffiliateType() {}
    
    // Convenience constructor to ensure the type code is always "TYP_AFF"
    public AffiliateType(String value) {
        setId(new CodeListId(value, "TYP_AFF"));
    }
}

4. Fix the Affiliate Association

Update the @ManyToOne association in Affiliate to map both columns of the composite key. You have two solid options:

Option A: Map to a Fixed Type Code Column

Add a dedicated column to Affiliate that’s always set to "TYP_AFF", then link it to the composite key:

@Entity
@Table(name = "aff")
public class Affiliate {
    // Other entity fields...
    
    // Fixed column to match the AffiliateType discriminator value
    @Column(name = "aff_type_code", nullable = false, updatable = false)
    private String affTypeCode = "TYP_AFF";
    
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name = "typ_aff", referencedColumnName = "val_string"),
        @JoinColumn(name = "aff_type_code", referencedColumnName = "id_code_list")
    })
    private AffiliateType affiliateType;
    
    // Getters and setters
}

Option B: Mark the Type Code Join Column as Non-Insertable/Updatable

If you don’t want to add a new column, you can reference the existing id_code_list column in aff (ensure it’s always populated with "TYP_AFF" via database default or app logic):

@Entity
@Table(name = "aff")
public class Affiliate {
    // Other entity fields...
    
    @ManyToOne
    @JoinColumns({
        @JoinColumn(name = "typ_aff", referencedColumnName = "val_string"),
        @JoinColumn(name = "id_code_list", referencedColumnName = "id_code_list", 
                   insertable = false, updatable = false, nullable = false)
    })
    private AffiliateType affiliateType;
    
    // Getters and setters
}

Why This Works

By explicitly mapping the composite primary key and ensuring the @ManyToOne association references all columns of that key, Hibernate can create a valid foreign key constraint that matches the structure of code_list. The discriminator value is now tied directly to the composite key’s typeCode field, which aligns perfectly with your single-table inheritance strategy.

内容的提问来源于stack exchange,提问作者Grechka Vassili

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:17:54