在这段代码中,如何为复合键生成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;
8 回答
要映射复合键,可以使用
EmbeddedId
orIdClass
注释 . 我知道这个问题并不严格关于JPA,但规范定义的规则也适用 . 所以他们在这里:使用IdClass
复合主键的类可能看起来像(可能是静态内部类):
而实体:
IdClass
注释将多个字段映射到表PK .使用EmbeddedId
复合主键的类可能看起来像(可能是静态内部类):
而实体:
@EmbeddedId
注释将PK类映射到表PK .差异:
从物理模型的角度来看,没有差异
@EmbeddedId
以某种方式更清楚地传达了密钥是复合密钥,当组合的pk本身是有意义的实体或在代码中重用时,IMO是有意义的 .@IdClass
可用于指定某些字段组合是唯一的,但这些字段组合没有特殊含义 .它们也会影响您编写查询的方式(使它们或多或少冗长):
IdClass
EmbeddedId
参考文献
JPA 1.0规范
第2.1.4节"Primary Keys and Entity Identity"
第9.1.14节"EmbeddedId Annotation"
第9.1.15节"IdClass Annotation"
你需要使用@EmbeddedId:
正如我在this article中解释的那样,假设您有以下数据库表:
首先,您需要创建包含复合标识符的
@Embeddable
:有了这个,我们可以通过用
@EmbeddedId
注释来映射使用复合标识符的Employee
实体:与
Employee
具有@ManyToOne
关联的Phone
实体需要通过两个@JoinColumn
映射从父类引用复合标识符:有关更多详细信息,请查看this article .
看起来你是从头开始这样做的 . 尝试使用可用的逆向工程工具,如Netbeans Entities from Database,至少可以自动完成基础知识(如嵌入式ID) . 如果你有很多 table ,这可能会成为一个巨大的问题 . 我建议避免重新发明轮子并使用尽可能多的工具来将编码减少到最小和最重要的部分,你打算做什么 .
The primary key class must define equals and hashCode methods
实现equals时,您应该 use instanceof 以允许与子类进行比较 . 如果Hibernate延迟加载一对一或多对一关系,您将拥有该类的代理而不是普通类 . 代理是子类 . 比较类名会失败 .
更技术上:您应该遵循Liskows替换原则并忽略对称性 .
下一个陷阱是使用 name.equals(that.name) 而不是 name.equals(that.getName()) 之类的东西 . 如果是代理,第一个将失败 .
http://www.laliluna.de/jpa-hibernate-guide/ch06s06.html
让's take a simple example. Let'说两个名为
test
和customer
的表被描述为:还有一个表可以跟踪
test
和customer
:我们可以看到表
tests_purchased
中的主键是复合键,因此我们将使用hbm.xml
映射文件中的<composite-id ...>...</composite-id>
标记 . 所以PurchasedTest.hbm.xml
看起来像:但它并没有在这里结束 . 在Hibernate中,我们使用session.load(
entityClass
,id_type_object
)来使用主键查找和加载实体 . 在复合键的情况下,ID对象应该是一个单独的ID类(在上面的例子中是一个PurchasedTestId
类) which just declares the primary key attributes like below :重要的是,我们还实现了两个函数
hashCode()
和equals()
,因为Hibernate依赖它们 .另一个选项是映射为ConfPath表中的复合元素的Map .
但是,此映射将受益于(ConfPathID,levelStation)上的索引 .
制图:
复合密钥类
实体类