关联映射
一对多双向关联
- 实体
package com.xingxue.day4.hibernate.demo1.domain;
import java.util.HashSet;
import java.util.Set;
// 一个班级对应多个老师,一个老师属于一个班级
public class ClassModel {
//标识字段
private Long id;
//业务字段
private String cname;
private String description;
//关联字段
private Set<TeacherModel> teacherModels = new HashSet<TeacherModel>();
public Set<TeacherModel> getTeacherModels() {
return teacherModels;
}
public void setTeacherModels(Set<TeacherModel> teacherModels) {
this.teacherModels = teacherModels;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
===============================================================================
package com.xingxue.day4.hibernate.demo1.domain;
public class TeacherModel {
private Long id;
private String tname;
private ClassModel classModel;
public ClassModel getClassModel() {
return classModel;
}
public void setClassModel(ClassModel classModel) {
this.classModel = classModel;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getTname() {
return tname;
}
public void setTname(String tname) {
this.tname = tname;
}
}
- 映射文件
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xingxue.day4.hibernate.demo1.domain.TeacherModel" table="t_teacher">
<id name="id" column="id">
<generator class="sequence">
<param name="sequence_name">
teacher_seq
</param>
</generator>
</id>
<property name="tname" column="tname"></property>
<!--通过 many2one 描述 关系:多对一的关系
name 属性: 设置关联的字段名称
class 属性: 关联的类型
column 子标签:设置多方的外键名称
-->
<many-to-one name="classModel" class="com.xingxue.day4.hibernate.demo1.domain.ClassModel" column="cid"/>
</class>
</hibernate-mapping>
===============================================================================
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.xingxue.day4.hibernate.demo1.domain.ClassModel" table="t_class">
<id name="id" column="id">
<generator class="sequence">
<param name="sequence_name">
class_seq
</param>
</generator>
</id>
<property name="cname" column="cname"></property>
<property name="description"></property>
<!-- set 标签 描述 关联字段的 类型
name 属性: 关联字段的名称
inverse 属性:就是描述是否当前实体是否放弃外键的维护,默认就是false,表示不放弃
设置为 true 表示 当前实体放弃外键的维护。
-->
<set name="teacherModels" inverse="false">
<!-- 配置多方表中的外键,使用 key 标签
column 属性:指定外键的名称
-->
<key>
<column name="cid"></column>
</key>
<!-- one2many 标签 描述 关系
class 属性:设置关联的类型
-->
<one-to-many class="com.xingxue.day4.hibernate.demo1.domain.TeacherModel"></one-to-many>
</set>
</class>
</hibernate-mapping>
- 关系维护(inverse):默认情况下,一方也可以维护外键的关系,多方必须维护外键的关系(也就是说,多方法不能设置 inverse属性),往往 一方应该放弃外键的维护,因为采用一方外键维护,会单独的发 update 语句去更新外键的值,造成多发sql 的情况。所以可以在一方的 set 标签上设置 inverse属性为 true 表示放弃外键的维护。
<set name="teacherModels" inverse="true">
- 关联对象导航图查询以及优化(fetch)
一方 可以配置 fetch:
select(默认的):先查主表,同过主表的记录中的id 去分别发sql 查询关联表数据。
join: 采用 left outter join 进行主从连接查询,如果采用 lazy 属性 失效。
subselect:只有在一方配置文件中才有该选项,在多方配置文件中没有该选项,在 hql 中 查询主表有多个记录的时候,在查询关联的数据的时候,就会采用 子查询。
多方 可以配置 fetch:
select(默认的):先查主表,同过主表的记录中的id 去分别发sql 查询关联表数据。
join: 采用 left outter join 进行主从连接查询,如果采用 lazy 属性 失效。
级联操作 (cascade)
cascade 属性: 一般 delete 不要去配。
save-update:保存当前实体,就会级联保存关联的实体
delete : 删除当前实体,级联删除关联的实体
all : save-update 和 delete
delete-orphan:孤儿删除,只能在 一对多关联中使用.主表是一方,从表多方,如果从表的记录没有关联主表的外键值,从表的该记录可以视为是孤儿,就会删除。
all-delete-orphan : all delete-orphan-
hql 关联查询
迫切左外连接
select c from ClassModel c left join fetch c.teacherModels ,发一条sql
左外连接
select c from ClassModel c left join c.teacherModels ,发两条from ClassModel c left join c.teacherModels:返回的类型是 Object[] 类型
多对多双向关联
详见代码,注意一般来说应该放弃一方的外键维护