HIbernate 事务并发处理 悲观锁&&乐观锁

事务并发的问题

1.脏读(dirty read):一个事务读到了另一个未提交的事务
2.不可重复读(non-repeatable read):一个事务中两次读同一行数据,可是这两次读到的数据不一样
3.幻读(phantom read):一个事务中两次查询,但第二次查询比第一次查询多了或少了几行或几列数据

事务隔离级别有4种:
1 - read-uncommitted
2 - read-committed
4 - repeatable read
8- serializable
为了解决问题考虑效率的情况下一般使用第二级别的隔离方式。但是不能解决不可重复读,但可以在hibernate种使用乐观锁和悲观锁解决。

悲观锁

悲观锁假设当前事务会被其他事务同时访问,避免当前事务的操作受到干扰,先锁定资源。
是一种使用数据库的锁。在load方法种设置LockMode.UPCRADE使得ddl语句后面添加for update。

@Test
	public void testPessimisticLock() {
		Session session = sf.openSession();
		session.beginTransaction();
		
		Account a = (Account)session.load(Account.class, 1, LockMode.UPGRADE);
		int balance = a.getBalance();
		//do some caculation
		balance = balance - 10;
		a.setBalance(balance);
		session.getTransaction().commit();
		session.close();
	}

乐观锁

乐观锁是假设当前事务不会别其他事务同时访问,当其他事务访问的时候再使用程序逻辑去解决。
当前事务加上Version字段,当事务结束的时候,version值加1.对比开始和提交时候的值,不一样将报错。在Version的方法上面添加@Version主机即可。`

private int version;
	@Version
	public int getVersion() {
		return version;
	}

Test

@Test
	public void testOptimisticLock() {
		Session session = sf.openSession();

		Session session2 = sf.openSession();

		
		
		
		session.beginTransaction();
		Account a1 = (Account) session.load(Account.class, 1);
		

		session2.beginTransaction();
		Account a2 = (Account) session2.load(Account.class, 1);
		
		a1.setBalance(900);
		a2.setBalance(1100);

		session.getTransaction().commit();
		System.out.println(a1.getVersion());

		session2.getTransaction().commit();
		System.out.println(a2.getVersion());

		session.close();
		session2.close();
	}

结果会在session2.getTransaction().commit();时报错。

发布了47 篇原创文章 · 获赞 5 · 访问量 2049

猜你喜欢

转载自blog.csdn.net/OVO_LQ_Start/article/details/104120344