在关系型数据库中,表与表之间的关系是通过外键来实现,而其中最常见的关系有两种:一对多和多对多。
在面向对象的世界,对象与对象之间的关系是通过从源对象到目标对象的对象引用实现。关系是一个对象含有的其他对象或者对象的集合,而在关系型数据库中,关系要么通过定义另一张表的外键建立,要么通过中间表建立。
在Java或者JPA的世界里,所有的关系都是单向性的,一个源对象保有目标对象的索引,并不能保证目标对象和源对象一样包含源对象的索引。这个关系型数据库就不一样了,在关系型数据库中,表之间的关系通过外键来实现,查询语句通过这个外键,可以进行正向和反向的查询。
ManyToMany多对多关系是关系型数据库中一种非常常见的表关系。
在JPA中,如果要实现ManyToMany关系,常常是利用的一种方式是中间表。所有的ManyToMany关系都需要一个JoinTable,在这个JoinTable中,通过JoinColumns定义了两个外键,一个外键来指向源表的主键,另一个外键指向目标表的主键,通常JoinTable的主键是两个外键的组合。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
双向ManyToMany
虽然在数据库中ManyToMany总是双向的,但是在对象模型中定义双向关系时,需要定义映射的发起方(管理方)和映射的接收方。发起方需要定义JoinTable,接收方则需要定义mappedBy。如果不使用mappedBy,则Jpa的实现者会认为,这种多对多关系是两个独立定义的关系,就会有重复的两行记录插入到JoinTable中。
1 2 3 4 5 6 7 8 9 10 |
|
双向关系的共同毛病
需要应用程序自己去维护它们(对象)之间的双向关系,否则就不同步(out of sync)。在写set方法或者,多对多关系中的add方法时,需要注意将自己的引用设置到包含的集合对象中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
多对多关系的管理方的选择
多对多关系的管理方的定义取决于JoinTable的定义方,至于由哪一边作为管理方,取决于业务的关系,所以并不固定。但是必须要理解的时,它们之间建立关系的方式(即谁管理谁)。举个例子,User和Group,这是一个常见的多对多关系,当你将管理方定义在Group这边时,你要做的是将User添加到Group,然后保存Group。而不能将Group添加给User,然后保存User。
应用级联
由某一方来管理对象的操作,需要应用级联属性,来说明是否将级联操作传递到对应的实体类上。如果你在存储一个对象时,该对象关联到另一个对象,而它们之间的关系没有使用级联,则会抛出异常,告诉你,需要先存储关联对象。
级联操作的类型有6种,分别是ALL,PERSIST,MERGE,REMOVE,REFRESH,DETACH。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
1
|
|
参考资料:
1.http://en.wikibooks.org/wiki/Java_Persistence/ManyToMany
2.http://stackoverflow.com/questions/4935095/jpa-hibernate-many-to-many-cascading