一、
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>中设置级联。
二、inservse
inverse表“是否放弃维护关联关系”(在Java里两个对象产生关联时,对数据库表的影响),在one-to-many和many-to-many的集合定义中使用,inverse=”true”表示该对象不维护关联关系;该属性的值一般在使用有序集合时设置成false(注意hibernate的缺省值是false)。
one-to-many维护关联关系就是更新外键。many-to-many维护关联关系就是在中间表增减记录。
注: 配置成one-to-one的对象不维护关联关系。inservse是集合的属性,但不适用在list集合中,因为这样list的顺序会失效。
例如:一对多中,在one这方放弃维护关联关系:
<map name="emps" inverse="true">
<key column="depart_id"/>
<map-key type="long" column="name"/>
<one-to-many class="Employee"/>
</map>
放弃前:
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: update Employee set depart_id=?, name=? where id=?
Hibernate: update Employee set depart_id=?, name=? where id=?
放弃后:
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
三、继承映射:
优点:方便。
缺点:但是每增加一个子类,就会改变表employee的结构,还有大量的null值。
方式一:一个类继承体系一张表
整个的集成体系用一张表,设计一张表employee:
type字段是一个由hibrnate自动生成的鉴别器,用来区分员工类型的。
Id name depart_id type skill sell
0 null null 普通员工
1 coding null 销售员
2 null 100 技术员
1、分别编写Skiller类和sell类,均继承employee类;
2、在映射文件中:每个子类不能设置为not null。
<?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" discriminator-value="0">
<id name="id" column="id">
<generator class="native"/>
</id>
<discriminator column="type" type="int"/> <!-- 鉴别器。hibrnate 用来区分不同的子类-->
<property name="name" unique="true"/>
<many-to-one name="depart" column="depart_id"/>
<subclass name="Skiller" discriminator-value="1">
<property name="skill"/>
</subclass>
<subclass name="Sales" discriminator-value="2">
<property name="sell"/>
</subclass>
</class>
</hibernate-mapping>
3、编写测试类:
public class TestExtends {
public static void main(String[] args) {
// TODO Auto-generated method stub
//add();
query(2);
}
public static Department add(){
Session s=null;
Transaction tx=null;
try{
s=HibrnateUtil.getSession();
tx=s.beginTransaction();
Department dep=new Department();
dep.setName("department one");
Employee e1=new Employee();
e1.setName("aaa");
e1.setDepart(dep);
Skiller e2=new Skiller();
e2.setName("bbb");
e2.setDepart(dep);
e2.setSkill("skill");
Sales e3=new Sales();
e3.setName("ccc");
e3.setDepart(dep);
e3.setSell(100);
s.save(dep);
s.save(e1);
s.save(e2);
s.save(e3);
tx.commit();
return dep;
}finally{
if(s!=null){
s.close();
}
}
}
public static void query(int id){
Session s=null;
Transaction tx=null;
try{
s=HibrnateUtil.getSession();
tx=s.beginTransaction();
Employee e=(Employee)s.get(Employee.class, id);
System.out.println("员工名字:"+e.getName());
System.out.println("员工类型:"+e.getClass());
tx.commit();
}finally{
if(s!=null){
s.close();
}
}
}
}
执行结果:
插入结果:
执行结果:只在一张表中查询。效率高。
方式二:每个子类一张表,存放子类所特有的属性,公共的属性是放在父类employee中的。
没有大量的null,大事表格数量多。
1、 在配置文件中:
<class name="Employee">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name" unique="true"/>
<many-to-one name="depart" column="depart_id"/>
<joined-subclass name="Skiller"> <!-- 子类单独映射成一张表 -->
<key column=" employee_id "/><!-- 子类的外键 -->
<property name="skill"/><!-- 子类的属性 -->
</joined-subclass>
<joined-subclass name="Sales">
<key column="employee_id "/>
<property name="sell"/>
</joined-subclass>
</class>
在测试类中:
插入结果:
查询结果:有两个左外连接。效率不高。
Hibernate: select employee0_.id as id3_0_, employee0_.name as name3_0_, employee0_.depart_id as depart3_3_0_, employee0_1_.skill as skill4_0_, employee0_2_.sell as sell5_0_, case when employee0_1_.employee_id is not null then 1 when employee0_2_.employee_id is not null then 2 when employee0_.id is not null then 0 end as clazz_0_ from Employee employee0_ left outer join Skiller employee0_1_ on employee0_.id=employee0_1_.employee_id left outer join Sales employee0_2_ on employee0_.id=employee0_2_.employee_id where employee0_.id=?
方式三:
混合使用“一个类继承体系一张表”和“每个子类一张表” (表结构)
<class name="Employee" table="employee">
<id name="id">
<generator class="native"/>
</id>
<discriminator column="type"/>
<property name="name"/>
<subclass name="Skiller">
<property name="net"/>
</subclass>
<subclass name=”Sales”">
<join table="sales">
<key column="employee_id"/>
<property name="sell"/>
</join>
</subclass>
</class>
执行结果:
查询结果:查询时,表格employee会和表格sales连接查询。
Hibernate: select employee0_.id as id3_0_, employee0_.name as name3_0_, employee0_.depart_id as depart4_3_0_, employee0_.skill as skill3_0_, employee0_1_.sell as sell4_0_, employee0_.type as type3_0_ from Employee employee0_ left outer join sales employee0_1_ on employee0_.id=employee0_1_.employee_id where employee0_.id=?
方式四:
每个具体类一张表,表中是子类的完整信息。
<class name="Employee" abstract="true">
<id name="id">
<generator class="hilo"/>
</id>
<property name="name"/>
<union-subclass name="Skiller" table="skiller">
<property name="skill"/>
</union-subclass>
<union-subclass name="Sales" table="sales">
<property name="sell"/>
</union-subclass>
</class>
主健不能是identity类型,如果父类是abstract=”true”就不会有表与之对应。
隐式多态,映射文件没有联系,限制比较多很少使用。
执行结果:
插入结果:
Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, id) values (?, ?, ?)
Hibernate: insert into Skiller (name, depart_id, skill, id) values (?, ?, ?, ?)
Hibernate: insert into Sales (name, depart_id, sell, id) values (?, ?, ?, ?)
查询结果:子查询
Hibernate: select employee0_.id as id3_0_, employee0_.name as name3_0_, employee0_.depart_id as depart3_3_0_, employee0_.skill as skill4_0_, employee0_.sell as sell5_0_, employee0_.clazz_ as clazz_0_ from ( select id, name, depart_id, order_id, null as skill, null as sell, 0 as clazz_ from Employee union select id, name, depart_id, order_id, skill, null as sell, 1 as clazz_ from Skiller union select id, name, depart_id, order_id, null as skill, sell, 2 as clazz_ from Sales ) employee0_ where employee0_.id=?