关联关系
类与类之间最普通的关系就是关联关系,而且关联是有方向的
1. 建立单向多对一关联关系(对象)
(1).配置单向多对一关联
Dept类 (部门表)
public class Dept implements Serializable{
private Byte deptNo; //部门编号
private String deptName; //部门名称
private String location; //部门地址
//GET SET 省略
}
Emp类(员工表 )
public class Emp implements Serializable{
private Integer empNo; //员工编号
private String eName; //员工姓名
private Dept dept; //所属部门
//GET SET 省略
}
Dept.hbm.xml(部门类的配置类)
<hibernate-mapping>
<class name="pojo.Dept" table="`DEPT`" schema="scott"
dynamic-update="true">
<id name="deptNo" column="`DEPTNO`" type="java.lang.Short">
<generator class="increment" />
</id>
<property name="deptName" type="java.lang.String" column="`DNAME`" />
<property name="location" type="java.lang.String" column="`LOC`" />
</class>
</hibernate-mapping>
Emp.hbm.xml(员工类的配置类)
<hibernate-mapping>
<class name="pojo.Emp" table="`EMP`" schema="scott"
dynamic-update="true">
<id name="empNo" column="`EMPNO`" type="java.lang.Integer">
<generator class="increment" />
</id>
<property name="eName" type="java.lang.String" column="`ENAME`" />
<property name="job" type="java.lang.String" column="`JOB`" />
<property name="sal" type="java.lang.Double" column="`SAL`" />
<property name="hireDate" type="java.util.Date" column="`HIREDATE`" />
<many-to-one name="dept" column="`DEPTNO`"
class="pojo.Dept"></many-to-one>
//column指的就是deot的外键,此处指的是EMP表的外键DEPTNO
</class>
</hibernate-mapping>
(2).实现持久化操作
以插入为列
EmpDao中关键代码:
public void save(Emp emp) {
this.currentSession().save(emp);
}
业务中的关键代码
public class EmpService {
EmpDao empDao = new EmpDao();
public void addNewEmp(Emp emp) {
Transaction tx = null;
Dept dept = null;
try {
tx = HibernateUtil.currentSession().beginTransaction();
empDao.save(emp);
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
}
测试方法的关键代码:
Emp emp=new Emp();
emp.seteName("张三");
Dept dept=new Dept();
dept.setDeptNo(new Short("10"));
emp.setDept(dept);
new EmpService().addNewEmp(emp);
测试类执行就可插入emp,dept各插入一条数据
也可做一些删除,查询的操作,这里就不一一举例了。
2. 建立双向一对多关联关系(集合)
上一大点建立了多对一,即多个用户属于一个部门,现在就是一对多的演示,即一个部门对应多个用户(以上实例为基础,修改)
(1).在Dept上加一个集合类型的emps属性
public class Dept implements Serializable{
private Set<Emp> emps = new HashSet<Emp>();
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
}
}
(2).在Dept中加入set配置
<set name="emps" cascade="save-update">
<key column="`DEPTNO`"></key>
<one-to-many class="pojo.Emp" />
</set>
//key 对应表的外键
//定义set类型的原因是emps属性为java.util.Set集合类型
(3).双向关联关系下的增删改操作
1.cascade属性
cascade属性值 | 描述 |
---|---|
none | 默认,当session操作当前对象时,忽略其他关联的对象 |
save-update | 当session的save(),update(),即saveOrUpdate()方法来保存或更新当前对象时,级联保存所有关联的瞬时状态的对象,并且级联更新所有关联的游离状态的对象 |
detele | detele方法删除当前对象时,会级联删除所有关联的对象 |
all | 包含save-update,delete的行为 |
对于cascade属性的认识:当属性值为none时,只能执行查询的操作;当属性值为save-update,就可以进行保存的操作,如果有主键,对数据库进行以主键update,如果没有主键直接进行save操作。如果属性值只是delete操作时,只可以进行删除的操作,那么all就可以进行任意操作
2.修改Dept.hbm.xml(设置cascade属性,进行删除的操作)
<set name="emps" cascade="save-update">
<key column="`DEPTNO`"></key>
<one-to-many class="pojo.Emp" />
</set>
3.Deptdao 关键代码
public class DeptDao extends BaseDao {
// 读取具体的Dept
public Dept load(Serializable id) {
return (Dept) currentSession().load(Dept.class, id);
}
// 删除
public void load(Dept dept) {
this.currentSession().delete(this.load(dept.getDeptNo()));
}
}
4.业务类 关键代码
public class DeptService{
DeptDao deptDao = new DeptDao ();
public void deleteDept(Dept dept) {
Transaction tx = null;
try {
tx = HibernateUtil.currentSession().beginTransaction();
deptDao .delete(dept);
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
5.测试类关键代码
Dept dept=new Dept();
dept.setDetpNo((byte)22);
new DeptService().deleteDept(dept);
运行该实例,hibernate会删除Dept对象及关联的Emp对象
> 元素的inverse属性 > 直译为反转,在Hibernate中,inverse属性指定了关联关系的方向。属性值有两个,即true,false,默认是false。关联关系中,inverse="false"为主动方,主动方会负责维护关联关系
3. 建立多对多关联关系(建立关系表)
以Project(项目表)和Emplyee(员工表),建立PROEMP表,表中设置项目表,员工表的外键,设置此表主键
(1).Project类
public class Project implements java.io.Serializable {
private Integer proid;
private String proname;
private Set<Employee> employees = new HashSet<Employee>();
//省略getter和setter方法
}
(2).添加Project.hbm.xml的配置类
<set name="employees" table="`PROEMP`" cascade="save-update">
<key column="`RPROID`"/>
<many-to-many class="pojo.Employee" column="`REMPID`"/>
</set>
//key的column指定PROEMP的外键RPROID
//many-to-many 的class属性指定集合中存放的是Employee对象,column属性指定PROEMP的外键RPROID
(3).ProjectDao的关键代码
public void save(Project project) {
this.currentSession().save(project);
}
(4).ProjectService的关键代码
public void addNewProject(Project project) {
Transaction tx = null;
try {
tx = HibernateUtil.currentSession().beginTransaction();
projectDao.save(project);
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null) {
tx.rollback();
}
}
}
(5).测试类
Employee employee = new Employee(1, "张三");
Employee employee2 = new Employee(2, "李四");
Project project = new Project(3, "一号项目");
Project project2 = new Project(4, "二号项目");
project.getEmployees().add(employee);
project.getEmployees().add(employee2);
project2.getEmployees().add(employee);
employee.getProjects().add(project);
employee.getProjects().add(project2);
employee2.getProjects().add(project);
ProjectService projectService = new ProjectService();
projectService.addNewProject(project);
projectService.addNewProject(project2);
总结:多对多就是建立一个两个表之间想关联的一个表
4. 延迟加载
用于设定加载策略的lazy属性
级别 | lazy属性值 |
---|---|
类级别 | 元素中lazy属性的可选值为true(延迟加载)和false(立即加载)。默认true |
一对多关联级别 | 元素的lazy属性可设置为true(延迟加载),extra(增强延迟加载)和false(立即加载).默认为true |
多对一关联级别 | <many-to-one》元素中的lazy属性的可选值为proxy(延迟加载),no-proxy(无代理延迟加载)和false(立即加载),默认为proxy |
一般都设置延迟加载,设置立即加载存在两大不足:
1.执行不必要的查询语句,影响查询性能
2.加载不需要的对象,增强系统开销,浪费内存空间