博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
阅读量:5296 次
发布时间:2019-06-14

本文共 5012 字,大约阅读时间需要 16 分钟。

Nhibernate 并发控制

【1】悲观并发控制

       正在使用数据的操作,加上锁,使用完后解锁释放资源。

使用场景:数据竞争激烈,锁的成本低于回滚事务的成本

缺点:阻塞,可能死锁

【2】乐观并发控制:

       所谓乐观,就是乐观的认为其他人没有在用该资源,资源的使用者不加锁。

      A 读取数据后,如果该数据被别人B修改,产生错误,A回滚事务并重新开始。

使用场景:数据竞争不激烈,回滚事务的成本低于锁的成本。

 

-----------------------------------------------------------------------------------------------------------

Nhibernate 支持乐观并发控制:

  通过使用<version>或<timestamp>,节点配置。

  注意: <version>要配置一定在<Id>节点之后。否则抛出配置错误。如下所示:

Customer.hbm.xmml

......

 

Order.hbm.xml

-------------------------------------------------------------------

 

使用<version>标签 配置,实现并发控制。

   原理:检查数据库的Version字段的版本值:插入前检查本身携带的Version是否等于现在数据库的Version值,如果

    【1】相等,插入成功,并且Vesion加保存带数据库。

    【2】不相等,插入失败,并且抛出NHibernate.StaleObjectStateException类型异常,抛异常:所以并不需要Nhibernate事务的支持,用来回滚事务,因为根本就没插入。

                    

 

   -------------------------------------更新(Update)并发测试------------------------------------------

 

Customer更新(Update)并发测试:

 

[TestMethod]       [ExpectedException(typeof(NHibernate.StaleObjectStateException))]       public void TestVessionByUpdate()       {           CustomerService customerService = new CustomerService();           OrderService orderService = new OrderService();           Customer customer = new Customer()           {               FirstName = "Test",               LastName = "TestVessionByUpdate",               Age = 10           };           customerService.Add(customer);           Customer customer1 = customerService.Get(customer.CustomerId);           Customer customer2 = customerService.Get(customer.CustomerId);           string customer1Name = "customer1";           customer1.FirstName = customer1Name;           customer2.FirstName = "customer2Test";           customerService.Update(customer2);  //能保存到数据库,Customer的version加1           customerService.Update(customer1);  //抛出异常NHibernate.StaleObjectStateException,更新失败。
}

 

Order更新(Update)并发测试:

[TestMethod]       [ExpectedException(typeof(NHibernate.StaleObjectStateException))]       public void TestVessionOrderByUpdateCustomer()       {           CustomerService customerService = new CustomerService();           OrderService orderService = new OrderService();           Customer customer = new Customer()           {               FirstName = "Test",               LastName = "TestVessionOrderByUpdateCustomer",               Age = 10           };           Order order1 = new Order()           {               OrderDate = DateTime.Now.AddMinutes(1),               Customer = customer           };           customer.Orders.Add(order1);           customerService.Add(customer);           Customer customer1 = customerService.Get(customer.CustomerId);           Customer customer2 = customerService.Get(customer.CustomerId);           customer1.Orders.First
().OrderDate = customer1.Orders.First
().OrderDate.AddDays(1); customer2.Orders.First
().OrderDate = customer2.Orders.First
().OrderDate.AddYears(1);
customerService.Update(customer2);  //Customer和Order都能保存到数据库,Order的version加1           customerService.Update(customer1);  //抛出异常NHibernate.StaleObjectStateException,更新失败。
}

 

 注意:

        注意已经把已经事务的相关代码注释掉了是为说明上面的并发控制并不需要事务的支持。Upadate的代码如下:

public void Update(Customer customer)        {            ISession session = _sessionManager.GetSession();            //ITransaction transaction = session.BeginTransaction();            try            {                session.Update(customer);                session.Flush();                //transaction.Commit();            }            catch (Exception)            {                //transaction.Rollback();                throw;            }            finally            {                session.Close();            }        }

 

    -------------------------------------删除(Update)并发测试------------------------------------------

如果启用了并发(即配置中添加了<version>标签属性),

那么删除的时候产生的SQL的Where语句会额外添加一个判断条件

           where customer.Version = 数据库里.vesesion

 

测试代码:

[TestMethod]       [ExpectedException(typeof(NHibernate.StaleObjectStateException))]       public void TestVessionDeleteCustomer()       {           CustomerService customerService = new CustomerService();           OrderService orderService = new OrderService();           Customer customer = new Customer()           {               FirstName = "Test",               LastName = "TestVessionDeleteCustomer",               Age = 10           };           customerService.Add(customer);           Assert.IsNotNull(customerService.Get(customer.CustomerId));           Customer customer1 = customerService.Get(customer.CustomerId);           Customer customer2 = customerService.Get(customer.CustomerId);           customerService.Delete(customer1);           customerService.Delete(customer2);       }

 

单元测试结果如下图所示:

      并发删除同一条记录,抛出NHibernate.StaleObjectStateException 类型的异常。

      故测试通过。

 

 

 

 

 

 

转载于:https://www.cnblogs.com/easy5weikai/p/3757052.html

你可能感兴趣的文章
IDEA------Error:java:无效的目标发行版:1/7
查看>>
python 取比当前值小的最小值
查看>>
[Tizen新闻]2013.10.12-三星放缓Tizen操作系统开发的脚步
查看>>
POJ 3421分解质因数
查看>>
学习python第六天
查看>>
java基础 -- Collections.sort的两种用法
查看>>
hdu 5768 容斥+模线性方程组
查看>>
Ogre中Mesh的加载过程详述
查看>>
SharePoint 2013 显示“以其他用户身份登录”菜单项
查看>>
2.硬件系统
查看>>
excel导入 导出 兼容各个版本服务器不装EXCEL也可以
查看>>
leetcode 46.全排列
查看>>
codeforces 697B Barnicle
查看>>
基于权限安全框架Shiro的登录验证功能实现
查看>>
Inside Microsoft SQL Server 2008: T-SQL Querying 读书笔记之查询优化
查看>>
ACM之java速成 (转)
查看>>
luoguP3834 【模板】可持久化线段树 1(主席树)
查看>>
fiddle--APP弱网测试
查看>>
C#委托-概念理解
查看>>
Linux忘记密码的解救方法
查看>>