数据库中存在的映射关系如下:
一对一: 人和身份证
一对多:顾客和订单
多对多:学生和课程
今天我们先介绍一对多关系的应该(这里是双向一对多)
双向一对多
首先我们建立表结构
从pojo结构上看就是一的一方存在多的一方集合
多的一方存在一的一方实体类
customers 实体类
public class Customers implements java.io.Serializable {
// Fields
private Long id;
private String name;
private Set orderses = new HashSet(0);
}
orders实体类
public class Orders implements java.io.Serializable {
// Fields
private Long id;
private Customers customers;
private String orderNumber;
映射文件
<hibernate-mapping>
<class name="com.wfg.Customers" table="customers" catalog="ontomany">
....
<set name="orderses" inverse="true" cascade="all">
<key>
<column name="CUSTOMER_ID" not-null="true" />
</key>
<one-to-many class="com.wfg.Orders" />
</set>
</class>
</hibernate-mapping>
- set元素包括以下属性:
– name: 设定待映射的持久化类的属性名,这里为Customer类的 orders属性
– cascade: 当取值为“save-update”,表示级联保存和更新。
– inverse:当取值为“true”,表示在双向关联中,这一端为镜像端。
表示关联关系的控制权,即按照关联的某一方的对象状态来同步跟新数据
库。为true,表示由对方负责;为false,表示由自己负责维护 - set元素还包含两个子元素:key和one-to-many,one-to-many元素设定所关联的持久化类, 此处为Order类,key元素设定与所关联的持久化类对 应的表的外键,此处为ORDERS表的CUSTOMER_ID字 段。
<many-to-one name="customers" class="com.wfg.Customers" fetch="select">
<column name="CUSTOMER_ID" not-null="true" />
</many-to-one>
**name : 设定待映射的持久化类的属性名称即Orders类里面的属性customers
Class: 设定持久化类的属性的类型,和基本类型的Type一样的功能,此处设定customer属性为Customer类型
column: 设定和持久化类的属性对应的表的外键,此处为ORDERS表的外键CUSTOMER_ID**
测试代码
Customers customers = new Customers();
customers.setId(new Long(1));
customers.setName("customers1");
//customers.setOrderses(new HashSet());
Orders o1 = new Orders(customers, "o1");
Orders o2 = new Orders(customers, "o2");
Orders o3 = new Orders(customers,"o3");
customers.getOrderses().add(o1);
customers.getOrderses().add(o2);
customers.getOrderses().add(o3);
//这里仅仅保存customers
session.save(customers);
执行效果
下面再细讲下cascade值的内容:
延迟加载
<set name="orderses" inverse="true" cascade="all" lazy="true">
lazy这个属性默认是true
这里发现一个现象就是先打印customers1又去查询的orders
这里我把session关闭后就抛出延迟加载的异常;
这里顺便把session.get()和session.load()方法也讲下:
- 即时加载:不管是否使用,马上会加载(从数据库取出放入内存),如session.get()方法。优点:响应速度快,不需要session一直打开状态。缺点:占用资源多。
- 延迟加载:代码执行后并不马上执行sql语句从数据库获取数据,而是在使用对象时才加载,如session.load()方法。注意,如果使用延迟加载,session要一直处于open状态,否则报异常。优点:占用资源少。缺点:响应速度慢,需要session一直打开状态。
自身一对多的概念
自身一对多用的比较多的地方就是在分类中使用最多即多级分类
实体类:
public class Categories implements java.io.Serializable {
// Fields
private Long id;
private Categories categories;
private String name;
private Set categorieses = new HashSet(0);
映射文件
<hibernate-mapping>
<class name="com.wfg.Categories" table="categories" catalog="ontomany">
<id name="id" type="java.lang.Long">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" length="15" />
</property>
<many-to-one name="categories" class="com.wfg.Categories" fetch="select">
<column name="CATEGORY_ID" />
</many-to-one>
<set name="categorieses" inverse="true" cascade="all">
<key>
<column name="CATEGORY_ID" />
</key>
<one-to-many class="com.wfg.Categories" />
</set>
</class>
</hibernate-mapping>
测试代码:
try {
Categories cat1 = new Categories(null, "cat1", new HashSet());
Categories cat2 = new Categories(null, "cat2.1", new HashSet());
Categories cat3 = new Categories(null, "cat2.2", new HashSet());
Categories cat4 = new Categories(null, "cat2.2.1", new HashSet());
Categories cat5 = new Categories(null, "cat2.2.2", new HashSet());
Categories cat6 = new Categories(null, "cat2.2.3", new HashSet());
//设定级联关系
cat1.getCategorieses().add(cat2);
cat1.getCategorieses().add(cat3);
cat2.setCategories(cat1);
cat3.setCategories(cat1);
//设定第二次级联关系
cat3.getCategorieses().add(cat4);
cat3.getCategorieses().add(cat5);
cat3.getCategorieses().add(cat6);
cat4.setCategories(cat3);
cat5.setCategories(cat3);
cat6.setCategories(cat3);
Categories cat8 = new Categories();
cat8.setId(new Long(2));
session.delete(cat8);
//session.save(cat1);
tx.commit();
} catch (Exception e) {
源代码:
链接:http://pan.baidu.com/s/1pLk9gi3 密码:lvim