• 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>

     测试代码清单一:

     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'。
    语句已终止。"}

    补充:如果注释掉

    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"

          不产生孤儿          删父时联级删子                                 删父时联级删子

          产生孤儿             抛异常                                            删父时联级删子

  • 相关阅读:
    使用Azure CLI实现自动关闭Azure虚拟机的脚本
    Azure自动化部署服务 (1)
    证书相关知识
    Azure上七层负载均衡APP Gateway
    简谈 Java 中的泛型通配符
    表单提交后为什么要重定向?
    eclipse 误删文件的恢复,代码的恢复
    书籍列表
    Mybatis Generator最完整配置详解
    学习spring mvc
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/3748230.html
Copyright © 2020-2023  润新知