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

Hibernate中复合外键关联场景下如何配置POJO的映射规则?

Hibernate复合主键与复合外键映射配置方案

1 定义Table1的联合主键类

Hibernate要求联合主键必须单独封装为独立类,同时满足三个规则:实现java.io.Serializable接口、重写equals()和hashCode()方法、提供无参构造方法。

import java.io.Serializable;
import java.util.Objects;

public class Table1Id implements Serializable {
    // 字段类型和实际表字段类型保持一致即可
    private String col1;
    private String col2;

    public Table1Id() {}

    public Table1Id(String col1, String col2) {
        this.col1 = col1;
        this.col2 = col2;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Table1Id table1Id = (Table1Id) o;
        return Objects.equals(col1, table1Id.col1) && Objects.equals(col2, table1Id.col2);
    }

    @Override
    public int hashCode() {
        return Objects.hash(col1, col2);
    }

    // 实际使用时需补充getter、setter方法
}

2 定义Table1主实体类

使用@IdClass注解绑定联合主键类,两个主键字段单独标记@Id注解:

import javax.persistence.*;

@Entity
@Table(name = "table1")
@IdClass(Table1Id.class)
public class Table1 {
    @Id
    @Column(name = "col1")
    private String col1;
    @Id
    @Column(name = "col2")
    private String col2;

    @Column(name = "col3")
    private String col3;
    @Column(name = "col4")
    private String col4;

    // 可选配置:如果需要从Table1侧关联查询关联的Table2记录可以添加
    @OneToMany(mappedBy = "table1", cascade = CascadeType.ALL)
    private List<Table2> table2List;

    // 实际使用时需补充无参构造、getter、setter方法
}

3 定义Table2实体类配置复合外键

使用@JoinColumns注解批量配置关联的外键字段,分别对应Table1的两个主键字段:

import javax.persistence.*;

@Entity
@Table(name = "table2")
public class Table2 {
    // 此处以c3为单主键示例,若Table2无单独主键,可同样用c1、c2作为联合主键
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "c3")
    private String c3;

    @Column(name = "c4")
    private String c4;

    // 配置多对一关联+复合外键
    @ManyToOne
    @JoinColumns(value = {
            @JoinColumn(name = "c1", referencedColumnName = "col1"),
            @JoinColumn(name = "c2", referencedColumnName = "col2")
    })
    private Table1 table1;

    // 实际使用时需补充无参构造、getter、setter方法
}

可选:传统XML映射配置

如果项目使用XML格式配置映射,可参考以下配置示例

table1.hbm.xml

<class name="com.example.Table1" table="table1">
    <composite-id class="com.example.Table1Id">
        <key-property name="col1" column="col1"/>
        <key-property name="col2" column="col2"/>
    </composite-id>
    <property name="col3" column="col3"/>
    <property name="col4" column="col4"/>
    <!-- 一对多关联配置 -->
    <set name="table2List" mapped-by="table1">
        <key>
            <column name="c1"/>
            <column name="c2"/>
        </key>
        <one-to-many class="com.example.Table2"/>
    </set>
</class>

table2.hbm.xml

<class name="com.example.Table2" table="table2">
    <id name="c3" column="c3">
        <generator class="native"/>
    </id>
    <property name="c4" column="c4"/>
    <!-- 多对一复合外键配置 -->
    <many-to-one name="table1" class="com.example.Table1">
        <column name="c1"/>
        <column name="c2"/>
    </many-to-one>
</class>

注意事项

  • 联合主键类的字段类型、名称要和实体类中标记@Id的字段完全对应
  • @JoinColumn的name属性是当前表(table2)的外键字段名,referencedColumnName是关联表(table1)的主键字段名,不要写反
  • 如果Table2本身需要用c1、c2作为联合主键,可以在Table2类上同样添加@IdClass注解,将c1、c2标记为@Id即可

内容的提问来源于stack exchange,提问作者Harshit Vijayvargia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 18:36:04