近来回顾Hibernate,对于单/双向多对一和多对多一直是一个难点和不容易理解的地方,特此写博文以便回顾
所用工具:eclipse luna、MySQL、windows7
先来说一下单向一对多,一对多,顾名思义,一个表中一条记录对应另一个表中的多条记录,如一个顾客可以有多个订单,而每一个订单只有一个顾客。这里就用顾客-订单建立持久化类模型和数据关联关系,Hibernate的配置文件省略,以节省篇幅
package com.demo.model;
public class Customer {
private Integer id;
private String name;
get/set
}
package com.demo.model;
public class Orders {
private Integer id;
private String name;
private Customer customer;
get/set
}
<hibernate-mapping>
<class name="com.demo.model.many2one.Customer" table="CUSTOMERS">
<id name="id" type="java.lang.Integer">
<column name="CUSTOMER_ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
</class>
</hibernate-mapping>
<hibernate-mapping package="com.demo.model.many2one">
<class name="Orders" table="ORDERS">
<id name="id" type="java.lang.Integer">
<column name="ORDER_ID" />
<generator class="assigned" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<!-- 映射多对一 -->
<!--
name:Order中对应的“一”的属性;
class:多对一中一那端对应的持久化类(POJO类);
column:会在Order对应的表中生成一个外键,关联的是给定的字段,通过column属性完成了多到一的映射
-->
<many-to-one name="customer" class="Customer"
column="CUSTOMER_ID" foreign-key="FK_CUSTOMER_ID_ORDER_ID"></many-to-one>
</class>
</hibernate-mapping>
Customer没什么值得注意的,主要是在Order这边(因为本例中单向多对一是从Order到Customer),使用了<many-to-one>元素来进行多对一映射,可以增加foreign-key属性指定要生成的外键的名称,注意记得把hbm.xml加入到Hibernate的配置文件中
下面来写几个小测试:
@Test
public void testSave() {
Customer customer = new Customer();
customer.setName("c-aa");
Order order1 = new Order();
order1.setName("o-aa");
Order order2 = new Order();
order2.setName("o-bb");
// 设定关联关系
order1.setCustomer(customer);
order2.setCustomer(customer);
// 保存 3个insert
// session.save(customer);
// session.save(order1);
// session.save(order2);
// 3个insert,2个update
session.save(order1);
session.save(order2);
session.save(customer);
}
为什么保存顺序不同,会多出2个update呢?
这是因为先保存order时,外键并没有对应,而在保存customer后,关联关系出现了,此时order的外键有参照了,于是为了修改order的外键,发送了update语句,建议先保存无外键的一端
再来看看获取:
@Test
public void testGet() throws Exception{
Order order = (Order) session.get(Order.class, 1);
System.out.println(order.getName());
Customer customer = order.getCustomer();
System.out.println(customer.getClass());
}
这是控制台返回的结果:
Hibernate:
select
order0_.ORDER_ID as ORDER_ID1_1_0_,
order0_.NAME as NAME2_1_0_,
order0_.CUSTOMER_ID as CUSTOMER3_1_0_
from
ORDERS order0_
where
order0_.ORDER_ID=?
o-aa
class com.demo.model.many2one.Customer_$$_jvst72a_1
可能大家看这个sql语句很正常,order的名称也查出来了,但是有个问题是,order里是有个customer属性的,customer.getClass()返回的应该是Customer的全类名,但返回的是com.demo.model.many2one.Customer_$$_jvst72a_1,是一个代理对象,这是Hibernate的懒加载机制的缘故,即在真正用到customer的属性和方法时,才去真正从数据库获取对应的customer,当然,也有出现懒加载异常的可能性,这里稍微一提,不再作过多解释,读者感兴趣的话可以找一下相关的资料看一下
最后来看一下删除:
@Test
public void testDelete() throws Exception {
Customer customer = (Customer) session.get(Customer.class, 1);
// session.delete(customer);// 会出现异常
Order order1 = (Order) session.get(Order.class, 1);
Order order2 = (Order) session.get(Order.class, 2);
session.delete(order1);
session.delete(order2);
session.delete(customer);
}
至于为什么会出现异常的原因,大家应该都知道了吧:因为customer关联着两个order,无法直接删除customer,只有先删除相关联的order后再删除customer
更新没有什么需要注意的地方,所以就不贴出代码了
转载于:https://blog.51cto.com/11230092/1753408