01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试
相关文章:
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>
测试代码清单一:
/// <summary>
/// 测试联级删除
/// Customer和Order配置了cascade="all",
/// 但是先在内存中解除从属关系,使之成为orphan (孤儿)
/// </summary>
[TestMethod]
public void TestDeleteCustomer_Cascade_All_RemoveOrderInMemery()
{
CustomerService customerService = new CustomerService();
OrderService orderService = new OrderService(); Customer customer = new Customer()
{
FirstName = "firstName_test1",
LastName = "Cascade",
Age = 10
}; Order order1 = new Order()
{
OrderDate = DateTime.Now,
Customer = customer
}; Order order2 = new Order()
{
OrderDate = DateTime.Now,
Customer = customer
}; //如果不加这一句:只添加Customer到数据,Order没有被添加到数据库
customer.Orders.Add(order1);
customer.Orders.Add(order2); //添加后customer.CustomerId被自动赋值
customerService.Add(customer);
Assert.IsNotNull(customerService.Find(customer.CustomerId));
Assert.IsNotNull(orderService.Find(order1.OrderId));
Assert.IsNotNull(orderService.Find(order2.OrderId)); //先在内存中解除从属关系,使之成为orphan (孤儿)
customer.Orders.Remove(order2); customerService.Delete(customer);
Assert.IsNotNull(customerService.Find(customer.CustomerId));
Assert.IsNotNull(orderService.Find(order1.OrderId));
Assert.IsNotNull(orderService.Find(order2.OrderId));
}
以上用测试代码:
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>
再执行下面测试代码清单二:
/// <summary>
/// 测试联级删除
/// Customer和Order配置了cascade="all-delete-orphan",
/// 但是先在内存中解除从属关系,使之成为orphan (孤儿)
/// </summary>
[TestMethod]
public void TestDeleteCustomer_Cascade_all_delete_orphan_RemoveOrderInMemery()
{
CustomerService customerService = new CustomerService();
OrderService orderService = new OrderService(); Customer customer = new Customer()
{
FirstName = "firstName_test1",
LastName = "Cascade",
Age = 10
}; Order order1 = new Order()
{
OrderDate = DateTime.Now,
Customer = customer
}; Order order2 = new Order()
{
OrderDate = DateTime.Now,
Customer = customer
}; //如果不加这一句:只添加Customer到数据,Order没有被添加到数据库
customer.Orders.Add(order1);
customer.Orders.Add(order2); //添加后customer.CustomerId被自动赋值
customerService.Add(customer);
Assert.IsNotNull(customerService.Find(customer.CustomerId));
Assert.IsNotNull(orderService.Find(order1.OrderId));
Assert.IsNotNull(orderService.Find(order2.OrderId)); //先在内存中解除从属关系,使之成为orphan (孤儿)
customer.Orders.Remove(order2); customerService.Delete(customer);
Assert.IsNull(customerService.Find(customer.CustomerId));
Assert.IsNull(orderService.Find(order1.OrderId));
Assert.IsNull(orderService.Find(order2.OrderId));
}
看图解:

结论:
cascade="all" cascade="all-delete-orphan"
不产生孤儿 删父时联级删子 删父时联级删子
产生孤儿 抛异常 删父时联级删子
01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试的更多相关文章
- 01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存
一.准备工作 [1]根据操作系统(位数)选择下载相应版本的MemCache, MemCache的下载和安装,参看: http://www.cnblogs.com/easy5weikai/p/37606 ...
- 01-03-02-2【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作-Save方法的一些问题
此文由于当时不知道NHibernate的Sava方法不是更新操作,不知道Save就是Add,造成如下荒唐的求证过程,但结论是对的 ,可报废此文,特此声明. NHibernate--Save方法: Cu ...
- 01-04-03【Nhibernate (版本3.3.1.4000) 出入江湖】Criteria API关联查询
Criteria API关联查询 如果说HQL查询还有需要了解点SQL语法知识,并不是完全彻底面向对象查询, 那么Criterial API就是完全面向对象的查询方式. public IList< ...
- 01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
Nhibernate 并发控制 [1]悲观并发控制 正在使用数据的操作,加上锁,使用完后解锁释放资源. 使用场景:数据竞争激烈,锁的成本低于回滚事务的成本 缺点:阻塞,可能死锁 [2]乐观并发控制: ...
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理
http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 管理NHibernate二级缓存 NHibernate二级缓存由ISessionF ...
- 01-08-04【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之命名缓存
http://www.cnblogs.com/lyj/archive/2008/11/28/1343418.html 可以在映射文件中定义命名查询,<query>元素提供了很多属性,可以用 ...
- 01-08-02【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider
第一步骤:hibernate.cfg.xml文件补上如下配置: <?xml version="1.0" encoding="utf-8"?> < ...
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
缓存的范围? 1.事务范围 事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结 ...
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态
以下属于不明来源资料: 引入 在程序运行过程中使用对象的方式对数据库进行操作,这必然会产生一系列的持久化类的实例对象.这些对象可能是刚刚创建并准备存储的,也可能是从数据库中查询的,为了区分这些对象,根 ...
- 01-06-01【Nhibernate (版本3.3.1.4000) 出入江湖】事务
Nhibernate事务的使用: public void Add(Customer customer) { ISession session = _sessionManager.GetSession( ...
随机推荐
- (转)hessian源码分析(一)------架构
在计费中心的对外交互这块采用了hessian,有必要对hessian的运行机理和源码做一定的解析. 大致翻了翻源码后,发现hessian的主要结构分客户端与服务端,中间基于http传输.客户端主要做的 ...
- idea基本
IntelliJ IDEA特色功能 IDEA所提倡的是智能编码,是减少程序员的工作,IDEA的特色功能有以下25点:智能的选取在很多时候我们要选取某个方法,或某个循环或想一步一步从一个变量到整个类慢慢 ...
- 济南学习 Day 4 T1 pm
幸运数字(number)Time Limit:1000ms Memory Limit:64MB题目描述LYK 最近运气很差,例如在 NOIP 初赛中仅仅考了 90 分,刚刚卡进复赛,于是它决定使用一些 ...
- .NET中的标识符、关键字 以及 .NET中的命名规范
1.关键字 C#定义了一些关键字(public/static/void/class/int/string),这些关键字是构成C#基本语法用的. VS中蓝色字的才是关键字. Main.String.Co ...
- 每天一个linux命令(1):which命令(转)
我们经常在linux要查找某个文件,但不知道放在哪里了,可以使用下面的一些命令来搜索: which 查看可执行文件的位置. whereis 查看文件的位置. locate ...
- 植物大战僵尸中文第二版和年度版 游戏分析及delphi源码
00413184 |. E8 77E30100 |CALL PlantsVs.00431500 ; 地上的物品00413189 |. 8D7424 10 ...
- 爱重启的windows,伤不起
.
- tomcat中server.xml文件解析
下面我们将讲述这个文件中的基本配置信息,更具体的配置信息见tomcat的文档 元素名 属性 解释 server port 指定一个端口,这个端口负责监听关闭tomcat的请求 shutdown 指定向 ...
- mdf与ldf文件如何还原到SQLserver数据库
现在又如下两个文件 需要用这两个文件还原数据库 那么该怎么去还原呢? 首先在D盘目录下建立一个文件夹test,然后将上图中的文件粘贴到该文件夹中. 接着在数据库中执行如下代码: EXEC sp_att ...
- 【Go】http server 性能测试
node秒java几街!pathon秒node几街 !go秒pathon几街! ab测试性能极佳的 package main import ( "fmt" "html/t ...