下面有两张表:1.CUSTOMER ID (PK) 2.ORDERS ID C_ID(FK)
下面是两表之间的代码:
// Create some data and persist it
tx = session.beginTransaction();
Customer customer = new Customer( " Tom " , new HashSet());
Order order = new Order();
order.setOrderNumber( " Tom_Order001 " );
order.setCustomer(customer); //将订单中的所属人属性加入
customer.getOrders().add(order); //取得用户订单list,追加新订单
session.save(customer);
tx.commit();
}
而这两句话就相当于在hibernate中产生两条SQL语句:
UPDATE ORDERS SET CUSTOMER_ID = ? WHERE ID = ?;
但这两条代码的功能是一样的,只是修改了一条ORDERS表的一条记录。
其实原理是这样的:
1.建立Orders对象到Customer对象的多对一关联关系:order.setCustomer(customer);
hibernate后台产生的SQL:UPDATE ORDERS SET ORDER_NUMBER='?', CUSTOMER_ID=? WHERE ID=?;
2.建立Customer对象到Order对象的一对多关联关系:customer.getOrders().add(order);
hibernate后台产生的SQL:UPDATE ORDERS SET CUSTOMER_ID=? WHERE ID=?;
重复执行多余的SQL语句会影响JAVA应用的性能,解决这一问题的办法是把<set>元素的inverse属性设为true,该属性的默认值为false:
name ="orders"
inverse ="true"
cascade ="save-update"
>
< key column ="CUSTOMER_ID" />
< one-to-many class ="mypack.Order" />
</ set >
反转属性,这时Customer端的关联只是Order端关联的镜像。这里Hibernate只会生成一条SQL语句:UPDATE ORDERS SET ORDER_NUMBER='?', CUSTOMER_ID=? WHERE ID=?;
即便注释掉了//customer.getOrders().add(order);也不会影响到hibernate的执行;反之,注释掉//order.setCustomer(customer); Hibernate将不会执行任何SQL。但还是推荐在程序中代码写入双关联,增加程序的健壮性,不会受到hibernate的影响。
另外解除关联的原理也是一样:customer.getOrders().remove(order); order.setCustomer(null);