Hibernate 的cascade属性的用法

hibernate一对多关系中,会用到级联操作.即:有collection的一端操作,被关联的表被自动操作.

这时有collection一端需要配置<set cascade="?">

即用在一对多的一方。

Cascade 属性值:

none:在保存、删除修改对象的时候,不考虑其附属物的操作

save-update:在保存、更新当前对象时,级联保存、更新附属物。

delete:在删除当前对象时,级联删除附属物。

all: 包含save-update和delete的操作,但不包括delete-orphan的操作。

delete-orphan:删除和当前对象解除关系的附属对象。

all-delete-orphan:所用情况。

例如:Team.hbm.xml

NONE:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!--
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.vo.Team" table="team" catalog="test" lazy="true">
        <id name="id" type="java.lang.Integer">
            <column name="ID" />
            <generator class="native" >
               
            </generator>
        </id>
        <property name="name" type="java.lang.String">
            <column name="Name" />
        </property>
        <set name="students"  cascade="none" lazy="false" batch-size="3">
            <key column="teamID"></key>
            <one-to-many class="com.vo.Student"></one-to-many>
        </set>
    </class>
</hibernate-mapping>

代码:

Session session = SessionUtil.getSession();
  Transaction tran = session.beginTransaction();
  Team team = (Team)session.get(Team.class, 4);

  Student addStu = new Student();

  addStu.setName("test");
  Student removeStu = (Student)session.get(Student.class, 15);
  team.getStudents().remove(removeStu);
  team.getStudents().add(addStu);
  tran.commit();
  session.close();

会报异常,异常原因是提示addStu为临时对象,他被持久化对象引用,而cascade="none",不能通过使用级联进行保存,所以异常是建议在清理缓存之前保存临时对象。

save-update

更改为cascade="save-update"

运行成功!对象已经被保存。但是发现所删除的student,并没有真正被删除,而只是将team_id设为了NULL,

结论是:从集合中删除这个对象并不会导致此对象在数据库中对应的记录删除,而只是将所对应的关联字段设置为了NULL。

delete

如果cascade设为delete,那么删除主题数据的时候,会级联删除所关联的对象。

delete-orphan

当你要删除集合中对象的时候,要采用这种方式:

Team team = (Team)session.get(Team.class, 10);
  Student removeStu = (Student)session.get(Student.class, 21);
  team.getStudents().remove(removeStu);

Team.hbm.xml

 <set name="students"  cascade="delete-orphan"  lazy="true" batch-size="3">
            <key column="teamID"></key>
            <one-to-many class="com.vo.Student"></one-to-many>
        </set>

Student.hbm.xml

 <many-to-one name="teamID" column="TeamID"  fetch="join"></many-to-one>

在STUDENT中不能设置cascade="all"

因为根据程序,当删除ID为21的学生时候,如果加了cascade="all"那么就是告诉程序去级联删除与之有关的TEAM,也就是将ID为10的TEAM也干掉了。如果干掉了ID为10的TEAM,那么与之有关的Student也将被删除,非常的危险。

所以一定要注意。

如 果设置cascade="all",则在调用session.delete(team);时,会删除TEAM下的所有STUDENT;如果是调用 team.getStudents().remove(stu);然后调用session.update(team)不会删除此STU,只会把该STU的 TEAM_ID设为NULL,所以想通过集合删除对象,需要设置cascade="delete-orphan"。

建议使用cascade="all-delete-orphan"。当然,根据项目、产品的实际需要,采用合适的配置项。

猜你喜欢

转载自freesky-zh.iteye.com/blog/2255982