java - 如何使用 JPA 和 Hibernate 映射复合键?

标签 java hibernate jpa orm composite-key

在这段代码中,如何为复合键生成一个Java类(如何在hibernate中复合键):

create table Time (
     levelStation int(15) not null,
     src varchar(100) not null,
     dst varchar(100) not null,
     distance int(15) not null,
     price int(15) not null,
     confPathID int(15) not null,
     constraint ConfPath_fk foreign key(confPathID) references ConfPath(confPathID),
     primary key (levelStation, confPathID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

最佳答案

要映射复合键,您可以使用 EmbeddedId IdClass 注释。我知道这个问题并不严格与 JPA 有关,但规范定义的规则也适用。所以他们在这里:

2.1.4 Primary Keys and Entity Identity

...

A composite primary key must correspond to either a single persistent field or property or to a set of such fields or properties as described below. A primary key class must be defined to represent a composite primary key. Composite primary keys typically arise when mapping from legacy databases when the database key is comprised of several columns. The EmbeddedId and IdClass annotations are used to denote composite primary keys. See sections 9.1.14 and 9.1.15.

...

The following rules apply for composite primary keys:

  • The primary key class must be public and must have a public no-arg constructor.
  • If property-based access is used, the properties of the primary key class must be public or protected.
  • The primary key class must be serializable.
  • The primary key class must define equals and hashCode methods. The semantics of value equality for these methods must be consistent with the database equality for the database types to which the key is mapped.
  • A composite primary key must either be represented and mapped as an embeddable class (see Section 9.1.14, “EmbeddedId Annotation”) or must be represented and mapped to multiple fields or properties of the entity class (see Section 9.1.15, “IdClass Annotation”).
  • If the composite primary key class is mapped to multiple fields or properties of the entity class, the names of primary key fields or properties in the primary key class and those of the entity class must correspond and their types must be the same.

带有 IdClass

复合主键的类可能看起来像(可能是静态内部类):

public class TimePK implements Serializable {
    protected Integer levelStation;
    protected Integer confPathID;

    public TimePK() {}

    public TimePK(Integer levelStation, Integer confPathID) {
        this.levelStation = levelStation;
        this.confPathID = confPathID;
    }
    // equals, hashCode
}

还有实体:

@Entity
@IdClass(TimePK.class)
class Time implements Serializable {
    @Id
    private Integer levelStation;
    @Id
    private Integer confPathID;

    private String src;
    private String dst;
    private Integer distance;
    private Integer price;

    // getters, setters
}

IdClass 注释将多个字段映射到表 PK。

使用 EmbeddedId

复合主键的类可能看起来像(可能是静态内部类):

@Embeddable
public class TimePK implements Serializable {
    protected Integer levelStation;
    protected Integer confPathID;

    public TimePK() {}

    public TimePK(Integer levelStation, Integer confPathID) {
        this.levelStation = levelStation;
        this.confPathID = confPathID;
    }
    // equals, hashCode
}

还有实体:

@Entity
class Time implements Serializable {
    @EmbeddedId
    private TimePK timePK;

    private String src;
    private String dst;
    private Integer distance;
    private Integer price;

    //...
}

@EmbeddedId 注解将 PK 类映射到表 PK。

区别:

  • 从物理模型上看,没有区别
  • @EmbeddedId 以某种方式更清楚地传达了 key 是复合 key 并且 IMO 有意义当组合的 pk 本身是一个有意义的实体或者它在您的代码中重用时 .
  • @IdClass 有助于指定某些字段组合是唯一的,但它们没有特殊含义

它们还会影响您编写查询的方式(使它们或多或少冗长):

  • IdClass

    select t.levelStation from Time t
    
  • 使用 EmbeddedId

    select t.timePK.levelStation from Time t
    

引用文献

  • JPA 1.0 规范
    • 第 2.1.4 节“主键和实体身份”
    • 第 9.1.14 节“EmbeddedId 注释”
    • 第 9.1.15 节“IdClass 注释”

关于java - 如何使用 JPA 和 Hibernate 映射复合键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3585034/

相关文章:

java - 无法将 int 转换为 String,/无法将 String 转换为 int [][]

集群环境中的数据库 ID 生成

java - 如何使用 Spring 3 配置 JPA?

java - 如何使用 Spring Data REST 的多态关联

java - Spring Data Jpa 和规范 - 如何处理 ManyToOne 和 ManyToMany 关系?

java - 如何使用 JPA 映射同一父类(super class)的实体之间的关系?

java - 设置数组列表格式

java - Android Studio 给 FOR 循环一个延迟

java - Tomcat 不卸载 Web 应用程序

java - 如何在可执行 jar 文件中运行 lombok 功能?