01-03-03【Nhibernate (版本3.3.1.4000) 出入江湖】cascade的测试
2014-05-23 17:55
411 查看
相关文章:
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对应的记录删掉
测试代码清单一:
补充:如果注释掉
也即,不产生孤儿,级联删除是成功的。即使是MS SQL Server(其他数据库没测试过)级联操作设置为:"不执行操作",如下图:
再执行下面测试代码清单二:
看图解:
结论:
不产生孤儿 删父时联级删子 删父时联级删子
产生孤儿 抛异常 删父时联级删子
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-02-1【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作--cascade 级联相关
- 01-03-01【Nhibernate (版本3.3.1.4000) 出入江湖】id标签的unsaved-value属性
- 01-04-03【Nhibernate (版本3.3.1.4000) 出入江湖】Criteria API关联查询
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之查询缓存
- 01-03-02-2【Nhibernate (版本3.3.1.4000) 出入江湖】CRUP操作-Save方法的一些问题
- 01-08-03【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之缓存管理
- 01-04-02【Nhibernate (版本3.3.1.4000) 出入江湖】HQL查询
- 01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询
- 01-08-05【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate二级缓存:第三方MemCache缓存
- 01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
- 01-06-01【Nhibernate (版本3.3.1.4000) 出入江湖】事务
- 01-04-01【Nhibernate (版本3.3.1.4000) 出入江湖】原生的SQL查询
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的一级缓存
- 01-05-01-1【Nhibernate (版本3.3.1.4000) 出入江湖】延迟加载及其class和集合(set、bag等)的Lazy属性配置组合对Get和Load方法的影响
- 01-08-02【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider
- 01-01-01【Nhibernate (版本3.3.1.4000) 出入江湖】配置文件
- 01-08-01【Nhibernate (版本3.3.1.4000) 出入江湖】NHibernate中的三种状态
- 01-08-04【Nhibernate (版本3.3.1.4000) 出入江湖】二级缓存:NHibernate自带的HashtableProvider之命名缓存
- 软件测试(第2版)_Paul学习03_01——Ch2举例_03
- 软件测试(第2版)_Paul学习03_01——Ch2举例_01