ITEEDU

Hibernate Gossip: cascade 的意义

在Java程序中,对象与对象之间会透过某些关系互相参考,如果有一个对象已经是持久化对象,被它参考的对象直觉上也应该要持久化,以维持对象之间关联的完整性,这是藉由可达性完成持久化(Persistence by reachability)的基本概念。

如果将对象之间的关联想象为一个树形图,从某一个持久化物件为树根出发,父节点若是持久化对象,则被父节点参考到的子节点应自动持久化,而另一方面,如果有一子节点没办法藉由任何的父节点来参考至它,则它没有被持久化的需求,它应从数据库中加以删除。

Hibernate并没有完全实现以上的概念,它让使用者自行决定自动持久化的方式,当对象之间被指定关联(例如多对一、一对多等),您可以决定被持久化对象关联的暂存对象是否进行自动持久化与如何自动持久化。

在Hibernate中是以映像文件中卷标上的cascade属性来设定,预设上是none,以 多对一 中的范例来说,如果不设定cascade为true,则您必须分别对User实例与Room实例进行储存:
Room room1 = new Room(); 
room1.setAddress("NTU-M8-419"); 
Room room2 = new Room(); 
room2.setAddress("NTU-G3-302"); 
        
User user1 = new User(); 
user1.setName("bush"); 
user1.setRoom(room1); 
        
User user2 = new User(); 
user2.setName("caterpillar"); 
user2.setRoom(room1); 
        
User user3 = new User(); 
user3.setName("momor"); 
user3.setRoom(room2); 

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

// 储存Room实例
session.save(room1); 
session.save(room2);
// 储存User实例
session.save(user1);
session.save(user2);
session.save(user3);

tx.commit();
session.close();
使用cascade自动持久化时,会先检查被关联对象的id属性,未被持久化的对象是否储存是藉由id属性的unsaved-value决定,预设是 null,也就是没有参考至任何值时储存对象,如果您使用int、long这样的原生型态(Primitive type)时,由于数据成员的初始会被设定为0,所以您必须自行指定默认值,例如(如果id的数据型态是long的话):
....
        <id name="id" column="id" unsaved-value="0">
            <generator class="native"/> 
        </id> 
....