01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制
Nhibernate 并发控制
【1】悲观并发控制
正在使用数据的操作,加上锁,使用完后解锁释放资源。
使用场景:数据竞争激烈,锁的成本低于回滚事务的成本
缺点:阻塞,可能死锁
【2】乐观并发控制:
所谓乐观,就是乐观的认为其他人没有在用该资源,资源的使用者不加锁。
A 读取数据后,如果该数据被别人B修改,产生错误,A回滚事务并重新开始。
使用场景:数据竞争不激烈,回滚事务的成本低于锁的成本。
-----------------------------------------------------------------------------------------------------------
Nhibernate 支持乐观并发控制:
通过使用<version>或<timestamp>,节点配置。
注意: <version>要配置一定在<Id>节点之后。否则抛出配置错误。如下所示:
Customer.hbm.xmml
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="Model"
assembly="Model"
default-lazy="true"> <class name="Model.Customer, Model"
table="Customer"
discriminator-value="0" lazy="false">
<!--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"/>
......
Order.hbm.xml
<class name="Model.Order, Model"
table ="[Order]"
discriminator-value="0" lazy="true">
<id name="OrderId"
column="OrderId"
type="int"
unsaved-value="0">
<!-- 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"/>
-------------------------------------------------------------------
使用<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 =
};
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 =
};
Order order1 = new Order()
{
OrderDate = DateTime.Now.AddMinutes(),
Customer = customer
}; customer.Orders.Add(order1);
customerService.Add(customer); Customer customer1 = customerService.Get(customer.CustomerId);
Customer customer2 = customerService.Get(customer.CustomerId); customer1.Orders.First<Order>().OrderDate = customer1.Orders.First<Order>().OrderDate.AddDays();
customer2.Orders.First<Order>().OrderDate = customer2.Orders.First<Order>().OrderDate.AddYears();
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 =
};
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 类型的异常。
故测试通过。
01-07-01【Nhibernate (版本3.3.1.4000) 出入江湖】并发控制的更多相关文章
- 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-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( ...
- 01-05-01-2【Nhibernate (版本3.3.1.4000) 出入江湖】立即加载实现--NHibernateUtil.Initialize()和添加fetch关键字的HQL查询
相关资料: http://www.cnblogs.com/lyj/archive/2008/10/29/1322373.html 问题的提出: 1.延迟加载,可能会引起session已经关闭的异常,例 ...
随机推荐
- zz 如何在Linux下创建与解压zip, tar, tar.gz和tar.bz2文件
January 2nd, 2009 at 10:31 pm Linux 解压, Linux, tar, tar.bz2, tar.gz, tgz, zip, 压缩, 打包, 文档 这么多年来,数据压缩 ...
- 济南学习 Day2 T2 am
[问题描述]有N个数,随机选择一段区间,如果这段区间的所有数的平均值在[l,r]中则你比较厉害.求你比较厉害的概率.[输入格式]第一行有三个数N,l,r,含义如上描述.接下来一行有
- 如何将HDL文件实例化到XPS中
本文转载自:http://xilinx.eetrend.com/blog/7073 硬件平台:ZedBoard 开发环境:XPS + ISE 操作系统:WinXP SP3 一直说要研究官方的例子 ...
- spring MVC项目中,欢迎页首页根路径到底是怎么设置的
0. 问题: 如何改mvc中项目的欢迎页,或者叫做根路径 一个东西快弄完了,就剩下一个问题,应该是个小问题.就是mvc项目的欢迎页,怎么给改下呢. 这个项目是通过mvn建立的,整个项目的原型就是spr ...
- JVM调优总结 -Xms -Xmx -Xmn -Xss(转载)
堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5G~2G:64为操作 ...
- linux传送文件至服务器
scp安全文件拷贝(基于ssh的登陆) 1.你想把本地/home下的文件linux.tar.gz传送至远端服务器10.108.125.30,远端服务器的账号名为name,保存至服务器/home ...
- c#枚举自定义,用于数据绑定。
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Enum)] public ...
- silverlight视频、音频
几天发现MediaElement播放不了wav格式的音频文件,在网上找到一篇解决的文章: http://www.cnblogs.com/rupeng/archive/2011/02/20/195936 ...
- 关于不同进制数之间转换的数学推导【Written By KillerLegend】
关于不同进制数之间转换的数学推导 涉及范围:正整数范围内二进制(Binary),八进制(Octonary),十进制(Decimal),十六进制(hexadecimal)之间的转换 数的进制有多种,比如 ...
- 11g RAC R2 日常巡检--Grid
一.巡检RAC数据库 1.1列出数据库 [grid@node1 ~]$ srvctl config database racdb [grid@node1 ~]$ 1.2列出数据库的实例 [grid@n ...