继承关系映射
cascade和inverse (Employee – Department)
1、 Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的cascade:
none,all,save-update ,delete, lock,refresh,evict,replicate,persist,
merge,delete-orphan(one-to-many) 。一般对many-to-one,many-to-many不设置级联,在<one-to-one>和<one-to-many>中设置级联。
2、 inverse表“是否放弃维护关联关系”(在Java里两个对象产生关联时,对数据库表的影响),在one-to-many和many-to-many的集合定义中使用,inverse=”true”表示该对象不维护关联关系;该属性的值一般在使用有序集合时设置成false(注意hibernate的缺省值是false)。
one-to-many维护关联关系就是更新外键。many-to-many维护关联关系就是在中间表增减记录。
注: 配置成one-to-one的对象不维护关联关系
课上小实例:
继承的映射:
方式一:
整个的继承体系就用一张表。设计一张表employee,表结构
字段有 id name depart_id type skill sell
0代表普通员工 null null
1代表技术员 coding null
2代表销售员 null 销售数量
(1)新建子类Skiller.java和Sales.java类:继承父类Employee,也有自己的属性
(2)分析表结构
(3)映射文件employee.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.hbsi.domain">
<!-- 方式一 -->
<class name="Employee" table="employee" discriminator-value="0">
<id name="id" column="id">
<generator class="native"/>
</id>
<!-- 定义鉴别器 type属性用来定义鉴别器的类型-->
<discriminator column="type" type="int"/>
<property name="name" column="name"/>
<many-to-one name="depart" column="depart_id"/>
<!-- 它的子类的映射 -->
<subclass name="Skiller" discriminator-value="0"><!-- 用来描述子类 discriminator-value="0",用来定义鉴别器的值-->
<property name="skill"/><!-- 特有的属性,不能加上not-null这样的属性,它是允许为空的! -->
</subclass>
<subclass name="Sales" discriminator-value="0">
<property name="sell"/>
</subclass>
</class>
</hibernate-mapping>
type--------鉴别器
<!-- 定义鉴别器 type属性用来定义鉴别器的类型-->
<discriminator column="type" type="int"/>
这种方法的缺点:关系模型不是很合理。
优点:效率高。
方式二:
每个子类一张表,不是存放子类的完整信息,而是存放子类所特有的属性的信息。子类共有的属性是放在employee中的。
employee skiller sales
id name depart_id employee_id skill employee_id sell
映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.hbsi.domain">
<!-- 方式二 -->
<class name="Employee" table="employee">
<id name="id">
<generator class="native"/>
</id>
<property name="name" column="name"/>
<many-to-one name="depart" column="depart_id"/>
<!-- 一个子类映射 -->
<joined-subclass name="Skiller" table="skiller">
<key column="employee_id"/>
<property name="skill"/>
</joined-subclass>
<joined-subclass name="Sales" table="sales">
<key column="employee_id"/>
<property name="sell"/>
</joined-subclass>
</class>
</hibernate-mapping>
。这两种方式都不是完美的,
优点:表格设计合理,没有大量没null的字段
缺点:效率不高。
方式三:
方式一和方式二混合使用,一个类继承体系一张表和每个子类一张表。
employee sales
id name depart_id type skill employee_id sell
映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.hbsi.domain">
<!-- 方式三 -->
<class name="Employee" table="employee" discriminator-value="0">
<id name="id">
<generator class="native"/>
</id>
<!-- 设置鉴别器 -->
<discriminator column="type" type="int"></discriminator>
<property name="name" column="name"/>
<many-to-one name="depart" column="depart_id"/>
<!-- 子类型 -->
<subclass name="Skiller" discriminator-value="1">
<property name="skill"/>
</subclass>
<subclass name="Sales" discriminator-value="2">
<join table="sales">
<key column="employee_id"/>
<property name="sell"/>
</join>
</subclass>
</class>
</hibernate-mapping>
方式四:
每个具体类一张表,保存的是子类的完整信息。
映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.hbsi.domain">
<!-- 方式四 -->
<class name="Employee" table="employee">
<id name="id">
<generator class="hilo"/>
</id>
<property name="name" column="name"/>
<many-to-one name="depart" column="depart_id"/>
<union-subclass name="Skiller" table="skiller">
<property name="skill"/>
</union-subclass>
<union-subclass name="Sales" table="sales">
<property name="sell"/>
</union-subclass>
</class>
</hibernate-mapping>
最后:编写测试类TestExtends.java
package com.hbsi.test;
import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.hbsi.domain.Department;
import com.hbsi.domain.Employee;
import com.hbsi.domain.Sales;
import com.hbsi.domain.Skiller;
import com.hbsi.hibernate.utils.HibernateUtil;
public class TestExtends {
public static void main(String[] args) {
// TODO Auto-generated method stub
add();
//查询
System.out.println("-------------查询的结果----------------");
query(1);
}
static void add(){
Session s=null;
Transaction tx=null;
try{
s=HibernateUtil.getSession();
tx=s.beginTransaction();
//增加
Department depart=new Department();
depart.setName("department one");
Employee emp1=new Employee();
emp1.setName("aaa");
emp1.setDepart(depart);
Skiller emp2=new Skiller();
emp2.setName("bbb");
emp2.setDepart(depart);
emp2.setSkill("coding");
Sales emp3=new Sales();
emp3.setName("ccc");
emp3.setDepart(depart);
emp3.setSell(1000);
//保存
s.save(emp1);
s.save(emp2);
s.save(emp3);
s.save(depart);
//提交事务
tx.commit();
}finally{
if(s!=null)
s.close();
}
}
static void query(int empId){
Session s=null;
Transaction tx=null;
try{
s=HibernateUtil.getSession();
tx=s.beginTransaction();
//查询
Employee emp=(Employee) s.get(Employee.class,empId);
System.out.println("员工的姓名:"+emp.getName()+" ,员工类型 :"+emp.getClass());
if(emp instanceof Skiller){
((Skiller) emp).getSkill();
}else if(emp instanceof Sales){
((Sales) emp).getSell();
}
//提交
tx.commit();
}finally{
if(s!=null)
s.close();
}
}
}