Hibernate多对一关联关系
两个持久化类。Customer 和 OrderForm
Customer 类。
package com.zcd.hibernate.manyToOne; public class Customer { private Integer id; private String name; public Customer() { } public Customer(String name) { this.name = name; } public Customer(Integer id, String name) { this.id = id; this.name = name; } //这里省略掉getter 和 setter 方法 }
OrderForm 类
package com.zcd.hibernate.manyToOne; public class OrderForm { private Integer id; private String name; private Customer customer; public OrderForm() { } public OrderForm(String name, Customer customer) { this.name = name; this.customer = customer; } public OrderForm(Integer id, String name, Customer customer) { this.id = id; this.name = name; this.customer = customer; } //这里省略掉getter 和 setter 方法 }
Customer 和 OrderForm 类的DAO 方法就是没有特别之处,这里也省略的。
//=======================分割线==========================================
下面是测试类调用Service 层。
Service 层的业务方法
public void save(Customer customer, OrderForm orderForm) { /* * OrderForm 为多端, Customer 为一端 * 这里先保存一端,再保存多端。 */ customerDao.save(customer); orderFormDao.save(orderForm); }
观察现象:这是基于以上 先保存一端,再保存多端的 Service 层的方法的。
//这个方法执行后有两条INSERT语句,能正常保存。 @Test public void testInsert() { Customer customer = new Customer(1, "顾客"); OrderForm orderForm = new OrderForm(1, "订单1", customer); testService.save(customer, orderForm); } //但是有一个地方需要注意,如果不做任何改变,继续执行这个方法一次,这里虽然还是指定新建的Customer 对象的id 为1, //OrderForm 对象的id 也为1,但是由于是新建的对象,所以在数据库里的他们的id 并不是1,都会在原来的表的基础上加1。比如这里他们的id 都为2, //那么此时orderform 表中的 id 为 2 的这条数据的外键列的是指向customer 表中的 id 为1 的数据还是 id 为2 的那条数据呢?实际上结果如下图。 //此时orderform 表中的id为2的数据的外键列指向的是customer表中的id为2的那条数据。个人认为是因为,在第二次保存的 orderForm 对象中的属性就是 //第二次保存的customer对象,而那个对象的保存在数据表中的id 为2,所以外键列的值也为2.
------------------------------------------------------------------------------------------------------------------------
如果在新建的对象中没有指定id,代码如下
@Test public void testInsert() { Customer customer = new Customer("顾客3");//没有指定id OrderForm orderForm = new OrderForm("订单3", customer);//没有指定id testService.save(customer, orderForm); }
此时正常保存,需要注意的是,此时也只想数据库发送了两条INSERT 语句(因为这是先保存一端,再保存多端的决定的。),现在看一下,修改Service层,先保存多端,在保存一端.
public void save(Customer customer, OrderForm orderForm) { /* * OrderForm 为多端, Customer 为一端 * 这里先保存多端,再保存一端。 */ orderFormDao.save(orderForm); customerDao.save(customer); }
此时正常保存,但是向数据库发送了两条INSERT 语句和一条UPDATE语句,说明先保存多端再保存一端的时候性能下降了。
================================2017-09-24更============================
为什么先保存多端在保存一端的时候性能会下降呢?
应该是这两个类的关联关系是由多端维护的(也就是在多端的表中有一个外键列保存了一端的ID,因为这样才能把两者关联起来。)
如果我们先保存多端,此时它关联的一端的那条记录还没保存,所以一端的那条记录的ID还没有确定。此时多端的表中的那条记录的外键列还是空的。所以得等到一端保存后再对多端进行更新。