设想一下部门与员工的关系,如果一个部门有几百个员工,则我们在存储数据的时候,需要一次的保存每个员工的信息,如果能在对部门进行操作的时候,把员工的信息也进行相对应的操作,那就方便多了,Hibernate中的Cascade便可以解决上述问题。
Cascade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似的操作,常用的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>中设置级联。
package org.hibernate.domain; import java.util.Set; public class Department { private int id; private String name; private Set<Employee> employees; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } @Override public String toString() { return "Department [id=" + id + ", name=" + name + ", employees=" + employees + "]"; } }
package org.hibernate.domain; public class Employee { private int id; private String name; private Department department; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } @Override public String toString() { return "Employee [id=" + id + ", name=" + name + ", department=" + department + "]"; } }
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.domain"> <class name="Department" table="department"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <set name="employees" cascade="save-update"> <key column="department_id" /> <one-to-many class="Employee" /> </set> </class> </hibernate-mapping>
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.domain"> <class name="Employee" table="employee"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <!-- 如果忽略了column这个属性那么默认的外键与实体的属性一致 --> <many-to-one name="department" column="department_id" /> </class> </hibernate-mapping>
测试类如下:
package org.hibernate.test; import java.util.HashSet; import java.util.Set; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.domain.Department; import org.hibernate.domain.Employee; import org.hibernate.util.HibernateUtil; import junit.framework.TestCase; public class CascadeTest extends TestCase { public void testCascade() { Session session = null; Transaction tx = null; try { Department department = new Department(); department.setName("department name"); Set<Employee> employees = new HashSet<Employee>(); Employee emp1 = new Employee(); emp1.setDepartment(department);// 对象模型:建立两个对象的关联 emp1.setName("emp1 name"); employees.add(emp1); Employee emp2 = new Employee(); emp2.setDepartment(department);// 对象模型:建立两个对象的关联 emp2.setName("emp2 name"); employees.add(emp2); department.setEmployees(employees); session = HibernateUtil.getSession(); tx = session.beginTransaction(); session.save(department); tx.commit(); } finally { if (session != null) session.close(); } } }
从代码中可以看到Hibernate只对部门进行了保存
控制台输出结果如下:
从结果可以看出,在保存部门的时候,员工的信息也进行了相应的更新。
设想在一个班级,如果辅导员需要记住整个专业同学的名字,这需要一段时间,但是如果只是让学生记住辅导员的名字,这就简单多了,Hibernate中的inverse属性就可以模拟此种现象
inverse"表示是否放弃维护关联关系“(在Java里两个对象产生关联时,对数据库表的影响),在one-to-many和many-to-many的集合定义中使用,inverse=”true”表示该对象不维护关联关系;该属性的值一般在使用有序集合时设置成false(注意hibernate的缺省值是false)。
one-to-many维护关联关系就是更新外键。
many-to-many维护关联关系就是在中间表增减记录。
注: 配置成one-to-one的对象不维护关联关系
还是上面部门与员工的例子,此时部门的配置文件如下:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.domain"> <class name="Department" table="department"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <set name="employees"> <key column="department_id" /> <one-to-many class="Employee" /> </set> </class> </hibernate-mapping>
测试类:
package org.hibernate.test; import java.util.HashSet; import java.util.Set; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.domain.Department; import org.hibernate.domain.Employee; import org.hibernate.util.HibernateUtil; import junit.framework.TestCase; public class InverseTest extends TestCase { public void testInverse() { Session session = null; Transaction tx = null; try { Department department = new Department(); department.setName("department name"); Set<Employee> employees = new HashSet<Employee>(); Employee emp1 = new Employee(); emp1.setDepartment(department);// 对象模型:建立两个对象的关联 emp1.setName("emp1 name"); employees.add(emp1); Employee emp2 = new Employee(); emp2.setDepartment(department);// 对象模型:建立两个对象的关联 emp2.setName("emp2 name"); employees.add(emp2); department.setEmployees(employees); session = HibernateUtil.getSession(); tx = session.beginTransaction(); session.save(department); session.save(emp1); session.save(emp2); tx.commit(); } finally { if (session != null) session.close(); } } }
控制台输出结果如下:
结果中的两条update语句由
department.setEmployees(employees);
而产生
如果此时在部门的配置文件中加入inverse属性:
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="org.hibernate.domain"> <class name="Department" table="department"> <id name="id"> <generator class="native" /> </id> <property name="name" /> <set name="employees" inverse="true"> <key column="department_id" /> <one-to-many class="Employee" /> </set> </class> </hibernate-mapping>
则此时部门与员工之间的关系就只由员工来维护,更改配置文件后控制台输出结果如下:
虽然测试类中还有
department.setEmployees(employees);
但此时的关系已由员工来维护了,所以update已经没有了,当然,配置了inverse属性,也可以提高
Hibernate的效率。