SpringData JPA复合主键 的使用

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

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

联合主键 : 表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 此处省略
}

你可能感兴趣的:(SpringData,JPA)