相关文章:
http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html
注意上面是hibernate,不是Nhibernate,这解释是否用于Nhibernate,自己验证。
cascade的取值范围:
all : 所有情况下均进行关联操作。
none:所有情况下均不进行关联操作。这是默认值。
save-update:在执行save/update/saveOrUpdate时进行关联操作。
delete:在执行delete时进行关联操作。
all的意思是save-update
+ delete
all-delete-orphan
的意思是当对象图中产生孤儿节点时,在数据库中删除该节点
all比较好理解,举个例子说一下all-delete-orphan:
Category与Item是一对多的关系,也就是说Category类中有个Set类型的变量items.
举个例子,现items中存两个Item,
item1,item2,如果定义关系为all-delete-orphan
当items中删除掉一个item(比如用remove()方法删除item1),那么被删除的Item类实例
将变成孤儿节点,当执行category.update(),或session.flush()时
hibernate同步缓存和数据库,会把数据库中item1对应的记录删掉
说在前头:
关于是否要级联操作,In my Opinion,还要看实际情况,
1.看关系是否属于识别性(如:鸟与翅膀的关系)与非识别性(独立个体:老师与学生的关系),
2.看业务需求。
3.看你老大的。。你懂的
-----------------------------------一言归正传:
Customer和Order的关系是1对多,即是:1个Customer有多个Order
测试一:cascade="all"
Customer.hbm.xml:
<class name="Model.Customer, Model"
discriminator-value="0">
。。。。
<set name="Orders" table="Order" generic="true"
inverse="true" cascade="all">
<key column="CustomerId" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Model.Order,Model"/>
</set>
</class>
</hibernate-mapping>
测试代码清单一:
1 /// <summary>
2 /// 测试联级删除
3 /// Customer和Order配置了cascade="all",
4 /// 但是先在内存中解除从属关系,使之成为orphan (孤儿)
5 /// </summary>
6 [TestMethod]
7 public void TestDeleteCustomer_Cascade_All_RemoveOrderInMemery()
8 {
9 CustomerService customerService = new CustomerService();
10 OrderService orderService = new OrderService();
11
12 Customer customer = new Customer()
13 {
14 FirstName = "firstName_test1",
15 LastName = "Cascade",
16 Age = 10
17 };
18
19 Order order1 = new Order()
20 {
21 OrderDate = DateTime.Now,
22 Customer = customer
23 };
24
25 Order order2 = new Order()
26 {
27 OrderDate = DateTime.Now,
28 Customer = customer
29 };
30
31 //如果不加这一句:只添加Customer到数据,Order没有被添加到数据库
32 customer.Orders.Add(order1);
33 customer.Orders.Add(order2);
34
35 //添加后customer.CustomerId被自动赋值
36 customerService.Add(customer);
37 Assert.IsNotNull(customerService.Find(customer.CustomerId));
38 Assert.IsNotNull(orderService.Find(order1.OrderId));
39 Assert.IsNotNull(orderService.Find(order2.OrderId));
40
41 //先在内存中解除从属关系,使之成为orphan (孤儿)
42 //customer.Orders.Remove(order2);
43
44 customerService.Delete(customer);
45 Assert.IsNotNull(customerService.Find(customer.CustomerId));
46 Assert.IsNotNull(orderService.Find(order1.OrderId));
47 Assert.IsNotNull(orderService.Find(order2.OrderId));
48 }
以上用测试代码:
customer.Orders.Remove(order2); //先在内存中解除从属关系,使之成为orphan (孤儿)
使得
order2变成孤儿后,删除Customer时会引发异常如下异常,说明数据库不允许删除。
上面的单元测试没有通过,而是抛出异常:
Bug跟踪调试,会发现,删除失败的原因是,发生了如下异常:
{"DELETE 语句与 REFERENCE 约束\"FK_CustomerOrders\"冲突。该冲突发生于数据库\"NHibernateSampleAutoCreateTable\",表\"dbo.Order\", column ‘CustomerId‘。\r\n语句已终止。"}
补充:如果注释掉
customer.Orders.Remove(order2); //先在内存中解除从属关系,使之成为orphan (孤儿)
也即,不产生孤儿,级联删除是成功的。即使是MS SQL Server(其他数据库没测试过)级联操作设置为:"不执行操作",如下图:
测试二:cascade="all-delete-orphan"
Customer.hbm.xml:
<class name="Model.Customer, Model"
discriminator-value="0">
<!--unsaved-value="0" 主键表中不需要定义,而是需要在子表中定义-->
<id name="CustomerId"
column="CustomerId"
type="int"
unsaved-value="0">
<generator class="native" />
<!-- unsaved-value used to be null and generator was increment in h2.0.3 -->
</id><!--version标签必须放在Id后面,否则出错-->
<version name="Version"/><property name="FirstName" >
<column name="Firstname" length="50" not-null="true"/>
</property><property name="LastName" type="String">
<column name="Lastname"/>
</property><property name="Age" type="int">
<column name="Age"/>
</property><set name="Orders" table="Order" generic="true"
inverse="true" cascade="all-delete-orphan">
<key column="CustomerId" foreign-key="FK_CustomerOrders"/>
<one-to-many class="Model.Order,Model"/>
</set>
</class>
再执行下面测试代码清单二:
1 /// <summary>
2 /// 测试联级删除
3 /// Customer和Order配置了cascade="all-delete-orphan",
4 /// 但是先在内存中解除从属关系,使之成为orphan (孤儿)
5 /// </summary>
6 [TestMethod]
7 public void TestDeleteCustomer_Cascade_all_delete_orphan_RemoveOrderInMemery()
8 {
9 CustomerService customerService = new CustomerService();
10 OrderService orderService = new OrderService();
11
12 Customer customer = new Customer()
13 {
14 FirstName = "firstName_test1",
15 LastName = "Cascade",
16 Age = 10
17 };
18
19 Order order1 = new Order()
20 {
21 OrderDate = DateTime.Now,
22 Customer = customer
23 };
24
25 Order order2 = new Order()
26 {
27 OrderDate = DateTime.Now,
28 Customer = customer
29 };
30
31 //如果不加这一句:只添加Customer到数据,Order没有被添加到数据库
32 customer.Orders.Add(order1);
33 customer.Orders.Add(order2);
34
35 //添加后customer.CustomerId被自动赋值
36 customerService.Add(customer);
37 Assert.IsNotNull(customerService.Find(customer.CustomerId));
38 Assert.IsNotNull(orderService.Find(order1.OrderId));
39 Assert.IsNotNull(orderService.Find(order2.OrderId));
40
41 //先在内存中解除从属关系,使之成为orphan (孤儿)
42 //customer.Orders.Remove(order2);
43
44 //customerService.Delete(customer);
45 Assert.IsNull(customerService.Find(customer.CustomerId));
46 Assert.IsNull(orderService.Find(order1.OrderId));
47 Assert.IsNull(orderService.Find(order2.OrderId));
48 }
看图解:
结论:
cascade="all" cascade="all-delete-orphan"
不产生孤儿 删父时联级删子
删父时联级删子
产生孤儿 抛异常
删父时联级删子