多表操作
一对多操作
客户和联系人的关系,一个客户可以对应多个联系人,一个联系人只能对应一个客户
配置一对多和多对一关系并配置外键
@OneToMany : 配置一对多关系
targetEntity :对方对象的字节码对象
mappedBy:对方配置关系的属性名称,这样主表就放弃外键维护权
cascade : 配置级联(可以配置到设置多表的映射关系的注解上),取值有:
CascadeType.ALL: 所有
CascadeType.MERGE:更新
CascadeType.PERSIST:保存
CascadeType.REMOVE:删除
fetch : 配置关联对象的加载方式,取值有:
EAGER :立即加载
LAZY :延迟加载
@JoinColumn : 配置外键
name:外键字段名称
referencedColumnName:参照的主表的主键字段名称
@ManyToOne : 配置多对一关系
targetEntity:对方的实体类字节码
在配置文件的entityManagerFactory的bean中注入jpa的配置信息
<!--注入jpa的配置信息
加载jpa的基本配置信息和jpa实现方式(hibernate)的配置信息
hibernate.hbm2ddl.auto : 自动创建数据库表
create : 每次都会重新创建数据库表
update:有表不会重新创建,没有表会重新创建表
-->
<property name="jpaProperties">
<props>
<prop key="hibernate.hbm2ddl.auto">create</prop>
</props>
</property>
在客户实体类中配置联系人集合
@OneToMany(targetEntity = LinkMan.class)
@JoinColumn(name="lkm_cust_id",referencedColumnName = "cust_id")
private Set<LinkMan> linkMans = new HashSet<>();
在客户实体类上(一的一方)添加了外键了配置,所以对于客户而言,也具备了维护外键的作用
在联系人实体类中添加客户对象
@ManyToOne(targetEntity = Customer.class,fetch = FetchType.LAZY)
@JoinColumn(name = "lkm_cust_id",referencedColumnName = "cust_id")
private Customer customer;
外键配置到了多的一方,就会在多的一方维护外键
测试一下保存操作
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class OneToManyTest {
@Autowired
private CustomerDao customerDao;
@Autowired
private LinkManDao linkManDao;
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testAdd() {
//创建一个客户,创建一个联系人
Customer customer = new Customer();
customer.setCustName("百度");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李");
customerDao.save(customer);
linkManDao.save(linkMan);
}
}
这时可以看到自动重建了表并插入了数据

但是数据库中的外键列为空

这里实体类中没有配置关系,在测试中并没有把customer和linkMan这两个对象关联起来,因此外键列显示为空,因此需要在save方法之前添加:
customer.getLinkMans().add(linkMan);
这个测试是在客户(一的一方)进行维护外键

这样就在从表中有了外键信息

我们也可以在联系人中(多的一方)维护外键
linkMan.setCustomer(customer);
这样就不会像在客户中维护外键多一句update语句

也可以达到同样的效果

两个同时维护外键也可以
linkMan.setCustomer(customer);//由于配置了多的一方到一的一方的关联关系(当保存的时候,就已经对外键赋值)
customer.getLinkMans().add(linkMan);//由于配置了一的一方到多的一方的关联关系(发送一条update语句)
但是由于一的一方可以维护外键,会发送update语句,如果我们不希望多余的update去维护外键,可以在一的一方放弃维护权。
在客户实体类中只声明一对多关系即可在一的一方放弃外键的维护权
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet<>();
这样一对多中一的一方就没有了外键的维护权,就没有了多余的update语句

级联添加和删除
在OneToMany注解中可以添加级联cascade
@OneToMany(mappedBy = "customer",cascade = CascadeType.ALL)
private Set<LinkMan> linkMans = new HashSet<>();
ALL就是增删改操作都可以级联
测试保存一个客户的同时,保存客户的所有联系人
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeAdd() {
Customer customer = new Customer();
customer.setCustName("百度1");
LinkMan linkMan = new LinkMan();
linkMan.setLkmName("小李1");
linkMan.setCustomer(customer);
customer.getLinkMans().add(linkMan);
customerDao.save(customer);
}

测试级联删除:删除1号客户的同时,删除1号客户的所有联系人
@Test
@Transactional //配置事务
@Rollback(false) //不自动回滚
public void testCascadeRemove() {
//1.查询1号客户
Customer customer = customerDao.findOne(1l);
//2.删除1号客户
customerDao.delete(customer);
}
