JPA / Hibernate:如何将复合外键与部分主键关联

时间:2014-07-23 17:30:05

标签: java hibernate jpa

我有两个表,每个表都有一个复合键:

CREATE TABLE Software (
  id int not null,
  version int not null,
  PRIMARY KEY (id, version)
);

CREATE TABLE System (
  name char(10) not null,
  version int not null,
  PRIMARY KEY (name, version)
);

现在,我需要一个可以表达概念的关联"软件对可以运行的系统版本有最低要求"。下表在数据库级别执行:

CREATE TABLE Requirement (
  software_id int not null,
  software_version int not null,
  system_name char(10) not null,
  system_version int not null,
  PRIMARY KEY (software_id, software_version, system_name),
  FOREIGN KEY (software_id, software_version) REFERENCES Software (id,version),
  FOREIGN KEY (system_name, system_version) REFERENCES System (name,version)
)

请注意,Requirement有三个字段作为主键。如果我要创建所有四个主要的,那么我可以表达一个以上的软件要求(即OpenLib v1.2依赖于Ubuntu 13.04和Ubuntu 13.10),而一个软件只能对给定的OS有一个要求(在例如,OpenLib v1.2依赖于Ubuntu 13.04)。

如何将其映射到JPA / Hibernate @Entity对象(使用注释)? (包括相关的OneToMany / ManyToOne关联。)

我面临的主要问题是,只有部分系统密钥用作需求中的主键。

注意:我不必遵守特定的遗留数据库,因此可以修改数据库设计。 我也对@EmbeddedId和/或@IdClass解决方案持开放态度。我希望遵守JPA。

我的代码中的属性需要通过getter / setter进行映射,而不是直接通过字段进行映射,但我想只使用字段的解决方案很好,只要转换是直接的。

谢谢。

**编辑28/8/2014 **

考虑以下我用来测试给出的解决方案的简单测试场景:

Software software = new Software(1,10);
System system = new System(2,20);
session.save(software);
session.save(system);
Requirement req = new Requirement();
req.setSoftware(software);
req.setSystem(system);
session.save(req);

1 个答案:

答案 0 :(得分:1)

您可以按如下方式对Requirement类进行编码:

@Entity
public class Requirement {

    @EmbeddedId
    private RequirementKey id;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "name", referencedColumnName = "name", insertable = false, updatable = false),
            @JoinColumn(name = "system_version", referencedColumnName = "version", insertable = false, updatable = false)
    })
    private System system;

    @ManyToOne
    @JoinColumns({
            @JoinColumn(name = "id", referencedColumnName = "id", insertable = false, updatable = false),
            @JoinColumn(name = "version", referencedColumnName = "version", insertable = false, updatable = false)
    })
    private Software software;

}

RequirementKey

@Embeddable
public class RequirementKey implements Serializable {
    int id;
    int version;
    String name;
}

我认为有更好的解决方案,但我无法弄清楚它是如何完成的。