分析场景:
departments对应多个员工employees:
departments.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.domain">
<class name="Department" table="departments">
<cache usage="read-only"/>
<id name="id" unsaved-value="0">
<generator class="native" />
</id>
<property name="name" />
<set name="employees" cascade="save-update" >
<key column="depart_id"/>
<one-to-many class="Employee"/>
</set>
</class>
</hibernate-mapping>
下面是employees.hbm.xml:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="cn.itcast.domain">
<class name="Employee" table="employees">
<cache usage="read-only"/>
<id name="id" column="id" unsaved-value="0">
<!--
<generator class="native"/>
-->
<generator class="hilo"/>
</id>
<!--
<discriminator column="type" type="int"/>
-->
<property name="name"/>
<property name="age"/>
<many-to-one name="depart" column="depart_id" lazy="false" fetch="join"/>
<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>
测试代码:
static void add() {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtils.getSession();
tx = session.beginTransaction();
//Department dep=(Department)session.get(Department.class, 1);
Department depart = new Department();
depart.setName("depart"+new Date().toLocaleString());
Set emps = new HashSet();
Employee emp = new Employee();
emp.setName("emp name:jimmy "+new Date().toLocaleString());
emp.setAge(10);
Employee emp1 = new Employee();
emp1.setName("emp name:kaka"+new Date().toLocaleString());
emp1.setAge(10);
emps.add(emp1);
emps.add(emp);
depart.setEmployees(emps);
session.save(depart);
//*/
tx.commit();
} finally {
if (session != null)
session.close();
}
}
输出语句:
Hibernate: insert into departments (name) values (?)
Hibernate: select next_hi from hibernate_unique_key for update
Hibernate: update hibernate_unique_key set next_hi = ? where next_hi = ? //这是hibernate4版本的多出的表
Hibernate: insert into employees (name, age, depart_id, id) values (?, ?, ?, ?)
Hibernate: insert into employees (name, age, depart_id, id) values (?, ?, ?, ?)
Hibernate: update employees set depart_id=? where id=?
Hibernate: update employees set depart_id=? where id=?
分析:看出有5条语句,先插入一条departments ,然后由于部门的set集合中 cascade="save-update" ,所以级联更新对应的员工数据,也即后面的两条插入员工数据,但是由于set集合默认的inverse为false,即有部门对象负责关联数据的维护工作,也即负责更新employees 表中的depart_id字段的值,所以后面又出现了两条更新员工的depart_id的语句。
问:如果去掉cascade="save-update" 怎么样?
答:报错org.hibernate.TransientObjectException
再问:如果设置cascade="save-update",同时设置inverse="true",怎么样?
答:输出三条语句,因为inverse="true",意味着由员工维护自己多的一方的数据,也即
部门department不再作为主控方,而将关联关系的维护工作交给关联对象employees 员工来完成。在保存department时,department不在关心employee的depart_id属性,必须由employee自己去维护,可是employee又没有emp.setDepart(depart);查询数据库可知道depart_id为null
insert into departments (name) values (?)
insert into employees (name, age, depart_id, id) values (?, ?, ?, ?)
insert into employees (name, age, depart_id, id) values (?, ?, ?, ?)