单向一对多是一个类中的一条记录可对应另一个类的多条记录;
比如一个部门可对应多个员工;
jpa中的实现步骤:
one-to-many的one类中添加一个many类类型的set;比如部门类Dept中添加一个员工类的Set<Emp>;
在set属性上方添加注解@one-to-many,表示映射one-to-many关系;
在set属性前添加注解@JoinColumn注解,注解的name属性为one类的主键,用来映射外键列名;
//一对多关联
@JoinColumn(name="id")
@OneToMany
private Set<Emp> empSet;
1.插入
代码:
//测试一对多
@Test
public void testInsert(){
Emp e1=new Emp();
e1.setBirthday(new Date());
e1.setName("诸葛村夫");
e1.setSalary(2000);
Emp e2=new Emp();
e2.setBirthday(new Date());
e2.setName("王司徒");
e2.setSalary(5000);
Dept dept=new Dept();
dept.setDname("文官");
Set set=new HashSet<Emp>();
set.add(e1);
set.add(e2);
dept.setEmpSet(set);
//执行保存操作
manager.persist(e1);
manager.persist(e2);
manager.persist(dept);
}
结果:
Hibernate:
insert
into
tb_emp
(birthday, name, salary)
values
(?, ?, ?)
Hibernate:
insert
into
tb_emp
(birthday, name, salary)
values
(?, ?, ?)
Hibernate:
insert
into
tb_dept
(dname)
values
(?)
Hibernate:
update
tb_emp
set
id=?
where
did=?
Hibernate:
update
tb_emp
set
id=?
where
did=?
可以看出,执行了三条插入语句和两条更新语句;
由于是one的一端通过外键来维持关联关系;
在保存many的一端时,就不会保存外键;
只能通过update语句来向many的一段插入外键;
因此无论先插入many还是先插入one都会有update语句;
2.查找
一对多映射,默认对many的一端使用懒加载的策略;
代码:
//测试一对多查询
@Test
public void testFind(){
manager.find(Dept.class, 1);
}
结果:
Hibernate:
select
dept0_.did as did1_0_0_,
dept0_.dname as dname2_0_0_
from
tb_dept dept0_
where
dept0_.did=?
可以看出只查询了dept,也就是one的一方;many的一方只会在用到时查询;
如果向改变加载策略;可在@OneToMany注解后面的fetch属性修改为EAGER;
3.删除
删除one的一端时,会将one一端关联的many一端的外键通过update语句置空;然后再删除one的一端;
如果想在删除one一端的同时把关联的many一端同时删除;可以在@OneToMany注解后面加上属性cascade={CascadeType.REMOVE};
@JoinColumn(name="id")
@OneToMany(cascade={CascadeType.REMOVE})
private Set<Emp> empSet;
代码:
//测试删除
@Test
public void testRemove(){
Dept dept=manager.find(Dept.class, 1);
manager.remove(dept);
}
结果:
Hibernate:
select
dept0_.did as did1_0_0_,
dept0_.dname as dname2_0_0_
from
tb_dept dept0_
where
dept0_.did=?
Hibernate:
update
tb_emp
set
id=null
where
id=?
Hibernate:
delete
from
tb_dept
where
did=?
4.修改
可以通过one的一方来修改many的一方;
例如代码:
//测试修改
@Test
public void testUpdate(){
Dept dept=manager.find(Dept.class,1);
dept.getEmpSet().iterator().next().setSalary(99999);
}
可改变关联的第一条数据的salary属性;