【Hibernate】【映射文件】【关系映射】
关系映射:即需要映射的属性,是一个实例对象.如员工的部门属性.
单向多对一(常用)
MySQL的表格
员工类中的属性
private Department dept;//dept_id
- 属性的映射
- 由员工管理,在员工的映射文件设置
<many-to-one name="dept" column="dept_id"/>
案例1
有一个员工A属于部门B,两者都没有存入数据库
情况1:session.save(员工);
- 结果:报错
- 原因:保存了员工后,没有找到外键对应的部门
情况2:session.save(先部门,再员工)
- 结果:正常发送两个insert的SQL
情况3:session.save(先员工,再部门)
- 结果:1.保存员工;2.保存部门,3.更新员工
- 原因:保存员工为持久化后,但其dept属性为临时状态,不受保存.保存部门后,dept又变成了持久化状态,导致员工状态变成脏的持久化状态,需要更新.
案例2
Employee e = (Employee)session.get(Employee.class, 1L);
Department dept = e.getDept();
System.out.println("_____________");
System.out.println(e); //使用了dept属性
结果:
- 查员工的SQL
- 横线
- 查部门
- 输出员工
原因:e.getDept();
取外键的对象,返回的是代理对象(延迟加载);使用前才会实例化.
外键的代理对比load()的代理
- load();返回的代理对象绝对不为null,不可以用代理对象==null来判断
- 外键的代理:返回的代理对象,可能为空,因为查询e时候,如果dept_id为null,就返回null,非null,就返回代理对象.代理对象==null可以用来判断
单向多对多(常用)
MySQL的表格(必有中间表)
-
Teacher类中的属性
- 由teacher管理student
private Set<Student> stus;//Teacher_Student Teacher_id/Student_id
- 属性的映射
<set name="stus" table="Teacher_Student" order-by="Student_id">
<key column="Teacher_id"/>
<many-to-many class="Student" column="Student_id"/>
</set>
<set name="属性名" table="中间表名">
<key column="对应己方的外键列"/>
<many-to-many class="他方的类" column="对应他方的外键列"/>
</set>
<!--set换成bag也会按id排序,bag对应的是list-->
<set name="stus" table="Teacher_Student" >
<key column="Teacher_id"/>
<many-to-many class="Student" column="Student_id"/>
</set>
//扩展按添加顺序排列
1.在Student类中添加记录添加顺序的属性并且声明
private Integer sequence;
2.在Teacher映射文件中的order-by="sequence"
单向一对多(常用)
外键依然标记在员工表的dept_id,只不过要将部门类中添加一个属性:
private Set<Employee> emps;//dept_id
属性的映射
<set name="emps">
<key column="dept_id"/>
<one-to-many class="Employee"/>
</set>
案例1
员工A所属部门B,两者都存入db
情况1.session.save(先部门,后员工)
- 结果:三条SQL;保存部门,保存员工,更新员工;
情况2.session.save(先员工,后部门)
- 结果:三条SQL;保存员工,保存部门,更新员工;
情况3.session.save(部门)
//单独保存部门(部门中有为保存的员工)会失败
- 结果:2条SQL;保存部门,更新员工因找不到而报错;
案例2
Department dept=(Department)session.get(Department.class,1L);
Set<Employee> emps = dept.getEmps();//返回代理对象
System.out.println("__________");
System.out.println(dept);//调用
-
结果:
- 查部门的sql
- 横线
- 查 员工的sql
- 输出部门
原因:dept.getEmps();
返回的是代理对象(延迟加载);使用前才会实例化.该代理对象也是决不为空,于load()一样.要用.size()方法来判断是否为空.
级联
可以通过one方来控制many方,<set cascade="XXX">
-
save-update:
- session.save(主对象):同时保存其集合中的从对象
- session.update(主对象):1.去持久化新增的从对象;2.修改游离的从对象;3.将已经丢出集合的从对象,其对应的外键设为null;
delete: 删除主对象,同时删除其集合中的从对象(在表中删除)
- all:save-update+delete
- delete-orphan:1.将外键设为null的从对象,从表中删除.2.将从集合中剔除的从对象,从表中删除.3删除主对象,也双光从对象.
- all-delete-orphan:上面的全部.订单就要用这个.
双向=一对多+多对一(常用)
数据库的表格不用,一样是员工表格有外键dept_id
更改映射文件
<!--员工-->
<class name="Employee">
<many-to-one name="dept" column="dept_id"/>
</class>
<!--部门-->
<class name="Department" inverse="true">
<set name="emps">
<key column="dept_id"/>
<one-to-many class="Employee"/>
</set>
</class>
inverse=”true”: 表示部门放弃对关系的管理,一切由员工的映射管理.
true:删除部门,同时会删对应的员工;而且会出现多余的SQL来维护二者关系
false:删除部门,只会将员工的外键为null
一对一(不常用)
QQ号对应QQ空间,可以使用QQ号的主键,作为外键指向QQ空间的主键;
即QQ空间的主键生成,是跟随QQ号的主键
<!--QQ号-->
<one-to-one name="zone">
<!--QQ空间-->
<!--声明主键生成方式依赖别的表的主键-->
<id name="id">
<generator class="foregn">
<param name="property">类中的QQ号属性名</param>
</generator >
</id>
<!--constained="true",表示被控制的-->
<one-to-one name="类中的QQ号属性名" constained="true">
组件关系
多个类,对应一个表,类与类是组件关系
类中的实例对象属性,就是多类中的其他属性进行一次包装,组件对象没有对应的表格
public class 公司{
private Long id;
private String name;
private Address 营业地址; //组件1
private Address 注册; //组件2
}
public class Address {
private String 省;
private String 城;
private String 街;
}
公司类的映射文件
<class name="公司">
<id></id>
<property></property>
<!--组件-->
<component name="营业地址">
<property name="省" column="表中的列1">
`
`
</component>
<!--组件-->
<component name="注册地址">
<property name="省" column="表中的列2">
`
`
</component>
</class>
继承关系
多个类,对应一个表,类与类是继承关系
映射文件(映射的类用父类!)
<class name="商品" discriminator-value="1">
<id> </id>
<property name="XX">
<!--声明表中区别的列名-->
<discriminator column="type" type="int">
<!--添加子类-->
<subclass name="书" discriminator-value="2">
<property name="作者"/>
</subclass >
<subclass name="衣" discriminator-value="3">
<property name="颜色"/>
</subclass >
</class>
此时 session.get(衣服.class,1L);
sql为 wher id=1 and type = 3;
上一篇: hibernate 映射组成关系