欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringData JPA复合主键 的使用

程序员文章站 2022-04-24 22:40:48
...

复合主键 和 联合主键的区别

复合主键 : 一张表中 , 两个字段 确定一条唯一数据 ;

联合主键 : 表A , 表 B 两张表 , 通过中间表 , 确定两张表的对应关系 ;
(中间表三个字段 : id , 表A_id, 表B_id) ; 此时中间表的id 称为 联合主键 ;

spring jpa 复合主键 的使用

使用场景 : 订单类的 , 订单编号 ORDER_NUM + 订单子项目 INNER_NUM , 两个字段 组成 复合主键 , 确定唯一数据 ;

  • 方式一 : 使用 @Embeddable 注解主键类 ; 然后 实体类 继承自主键类 ; (该方式书写简洁, 但是不易懂)

1 . 编写一个复合主键类 ; 命名可以在 实体类名后 + PK 用于 区分 主键类 ;

@Embeddable // 1. 在复合主键的类上,使用注解@Embeddable
public class OrderPK implements Serializable { // 2. 实现Serializable接口(否则会报错);

    @Column(name = "ORDER_NUM")
    private String orderNum; // 主单号
    @Column(name = "INNER_NUM")
    private String innerNum; // 子项目

    // 3. 无参构造
    //          有默认的public无参数的构造方法(在我这个实例中,我没有添加有参构造方法,所以采用默认的构造方法)
    //          如果你在实体类里有有参构造方法,那么一定要有一个无参构造方法,否则运行的时候会报错

    // 4. 重写equals和hashCode方法。
    //          equals方法用于判断两个对象是否相同,EntityManger通过find方法来查找Entity时,
    //          是根据equals的返回值来判断的。
    //          hashCode方法返回当前对象的哈希码
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof OrderPK)) return false;

        OrderPK orderPK = (OrderPK) o;

        if (orderNum != null ? !orderNum.equals(orderPK.orderNum) : orderPK.orderNum != null) return false;
        return innerNum != null ? innerNum.equals(orderPK.innerNum) : orderPK.innerNum == null;
    }

    @Override
    public int hashCode() {
        int result = orderNum != null ? orderNum.hashCode() : 0;
        result = 31 * result + (innerNum != null ? innerNum.hashCode() : 0);
        return result;
    }

    // 生成 get set toString 此处省略
}

2 . 编写实体类 , 继承 主键类;

@Entity
@Table(name = "ORDER")
public class Order extends OrderPK {

    // 复合主键要用这个注解
    @EmbeddedId
    private OrderPK id;

    // 复合主键的两个字段, 在实体类中,就不用写了

    @Column(name = "OTHER_FIELD")
    private String otherField; // 其他字段

   // 生成 get set toString 此处省略
}
  • 方式二 : 采用 @IdClass 来注解复合主键; ( 推荐 , 复合主键字段, 在实体类中, 直接有体现 , 看起来简单明了)
    1 . 编写一个复合主键类;
// @Embeddable
public class OrderPK implements Serializable {

    // @Column(name = "ORDER_NUM")
    private String orderNum; // 主单号

    // @Column(name = "INNER_NUM")
    private String innerNum; // 子项目

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof OrderPK)) return false;

        OrderPK orderPK = (OrderPK) o;

        if (orderNum != null ? !orderNum.equals(orderPK.orderNum) : orderPK.orderNum != null) return false;
        return innerNum != null ? innerNum.equals(orderPK.innerNum) : orderPK.innerNum == null;
    }

    @Override
    public int hashCode() {
        int result = orderNum != null ? orderNum.hashCode() : 0;
        result = 31 * result + (innerNum != null ? innerNum.hashCode() : 0);
        return result;
    }

   // 生成 get set toString 此处省略

}

2 . 编写实体类

@Entity
@Table(name = "ORDER")
@IdClass(OrderPK.class) // 添加 @IdClass 注解 , 指定 复合主键类
public class Order implements Serializable { // 不用再继承 复合主键类

	//  @EmbeddedId
	//  private OrderPK id;

    @Id // 添加复合主键标识
    @Column(name = "ORDER_NUM")
    private String orderNum; // 主单号

    @Id // 添加复合主键标识
    @Column(name = "INNER_NUM")
    private String innerNum; // 子项目

    @Column(name = "OTHER_FIELD")
    private String otherField; // 其他字段

    // 生成 get set toString 此处省略
}