Java JPA/Hibernate:如何将复合外键与部分主键关联
我有两个表,每个表都有一个复合键:Java JPA/Hibernate:如何将复合外键与部分主键关联,java,hibernate,jpa,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 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)
);
现在,我需要一个关联,在这里我可以表达“软件对它可以运行的系统版本有最低要求”的概念。下表在DB级别执行此操作:
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)
)
请注意,需求有三个字段作为主键。如果我将所有四个都设置为主,那么我可以表示一个软件的多个需求(即OpenLib v1.2依赖于Ubuntu 13.04和Ubuntu 13.10),而一个软件对于给定的操作系统只能有一个需求(在本例中,OpenLib v1.2依赖于Ubuntu 13.04)
如何将其映射到JPA/Hibernate@Entity对象(使用注释)?(包括相关的一通/多通协会。)
我面临的主要问题是,在需求中,只有部分系统密钥被用作主键
注意:我不必遵守特定的遗留数据库,因此可以修改数据库设计。
我也对@EmbeddedId和/或@IdClass解决方案持开放态度。不过,我更愿意遵守JPA
在我的代码中,属性需要通过getter/setter映射,而不是直接通过字段映射,但我想只使用字段的解决方案是可以的,只要转换是直接进行的
多谢各位
**编辑2014年8月28日**
考虑以下我用来测试给定解决方案的简单测试场景:
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);
您可以按如下方式对
需求类进行编码:
@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;
}
我认为有更好的解决方案,但我不知道如何实现。不起作用:系统变量和软件变量都引用数据库中的同一列“版本”。请注意,需求中有4列,两个“版本”是不同的。@Filippo那么,您的观点是在需求中有四列还是三列?我上面的代码假设您想要有三列(每列都属于需求PK),并且它在Hibernate 4.3.5和JPA 2.1.4下工作。三个是PK,一个不是。在这四列中,两列为FK,表示软件,两列为FK,表示系统。名为system_version的列不是PK的一部分,但它在系统中(与软件_version不同)。查看数据库布局的SQL语句。@Filippo查看一下更新,现在它生成了Requirement
表,表中有四列,其中三列为PK,我们将尝试。尽管我对system\u版本联接列定义中的“insertable=false,Updateable=false”感到困惑。hibernate会插入值吗?恐怕这栏会空着。。。