JPA实体映射——一对多关系映射(上)
依照上一节的案例,我们来拆解一对多的关系怎么使用,首先还是把业务关系图弄出来。
业务案例图
从图中我们知道,研究所和部门是一对多关系,今天我们来展示,一对多设计的最佳实践。
我们知道在JPA的实体设计中,一对多的关系可以设计成单向关联,也可以设计成双向关联。今天我们一步一步来实践各种设计,从而总结出最佳实践。
###Unidirectional @OneToMany###研究所实体 port javax.persistence.*; import java.io.Serializable; import java.util.HashSet; import java.util.Set; @Entity @Table(name = "institutes") public class Institute implements Serializable { @Id @GeneratedValue private Long id; @OneToMany( cascade = CascadeType.ALL, orphanRemoval = true ) private Set
工具类就不展示啦,可以查看https://devnote.pro/noteweb/docs/10000020363496/contents/10000063133496
###测试类 import com.jpa.demo.model.undirectional.Department; import com.jpa.demo.model.undirectional.Institute; import org.junit.Test; public class InstituteDaoTest { @Test public void testSaveInstitute(){ Institute institute = new Institute("深圳研究所"); institute.getDepartments().add(new Department("深圳研究所1部")); institute.getDepartments().add(new Department("深圳研究所2部")); institute.getDepartments().add(new Department("深圳研究所3部")); InstituteDao dao = new InstituteDao(); dao.save(institute); } }查看日志信息如下:
Hibernate: create table departments ( id bigint not null, name varchar(255), primary key (id) ) Hibernate: create table institutes ( id bigint not null, name varchar(255), primary key (id) ) Hibernate: create table institutes_departments ( Institute_id bigint not null, departments_id bigint not null, primary key (Institute_id, departments_id) ) Hibernate: alter table institutes_departments drop constraint if exists UK_67unewuyoqel2nu2ef8me1hyv Hibernate: alter table institutes_departments add constraint UK_67unewuyoqel2nu2ef8me1hyv unique (departments_id) Hibernate: create sequence hibernate_sequence start with 1 increment by 1 Hibernate: alter table institutes_departments add constraint FK3lq3buf7j6k7is3q1lurp2j91 foreign key (departments_id) references departments Hibernate: alter table institutes_departments add constraint FKlqld2ri9e0qmvhwy6nnany0o9 foreign key (Institute_id) references institutes Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: insert into institutes (name, id) values (?, ?) Hibernate: insert into departments (name, id) values (?, ?) Hibernate: insert into departments (name, id) values (?, ?) Hibernate: insert into departments (name, id) values (?, ?) Hibernate: insert into institutes_departments (Institute_id, departments_id) values (?, ?) Hibernate: insert into institutes_departments (Institute_id, departments_id) values (?, ?) Hibernate: insert into institutes_departments (Institute_id, departments_id) values (?, ?)首先,我们知道单向数据关联,生成了三张表分别是departments,institutes还有institutes_departments
然后在中间表的department_id上建立唯一约束,最后在中间表的字段上建立外键,分别指向各自的表主键。
我在保存数据库的时候,首先在institutes上插入一条数据,然后在departments上插入三条数据,最后插入institutes_departments表对应的数据,这样这个一对多的关系就建立起来。
这种设计显然存在很多问题:
1、生成了一个冗余的中间表
2、发出了多条SQL执行语句
3、建立了两个外键,我们需要更多的缓存
下面我们看看单向关系的另一种@OneToMany
###Unidirectional @OneToMany with @JoinColumn这次我们只需要增加一个注解
###研究所实体修改 @OneToMany( cascade = CascadeType.ALL, orphanRemoval = true ) @JoinColumn(name = "department_id") private Set同理,我们执行测试方法后,日志信息如下:
Hibernate: create table departments ( id bigint not null, name varchar(255), department_id bigint, primary key (id) ) Hibernate: create table institutes ( id bigint not null, name varchar(255), primary key (id) ) Hibernate: create sequence hibernate_sequence start with 1 increment by 1 Hibernate: alter table departments add constraint FK3ttxjsckxb3vwld1idf7a3r29 foreign key (department_id) references institutes Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: call next value for hibernate_sequence Hibernate: insert into institutes (name, id) values (?, ?) Hibernate: insert into departments (name, id) values (?, ?) Hibernate: insert into departments (name, id) values (?, ?) Hibernate: insert into departments (name, id) values (?, ?) Hibernate: update departments set department_id=? where id=? Hibernate: update departments set department_id=? where id=? Hibernate: update departments set department_id=? where id=?从日志信息可以看出,这次只生成了两个表institutes和departments,并且在departments上多了一个department_id,这个字段实际上就是我们在研究所实体上配置的外键。从SQL执行可以看出,插入的语句没有啥变化,只不过多了三个更新外键字段的语句。总的说来,有所改善,但是效果不是最好。
今天我们暂时学习到这里,当然这里还出有一些有意思的问题需要探讨。我们下一节继续。欢迎讨论。