Hibernate悲观锁-乐观锁

首先说一下数据库事务隔离级别

READ UNCOMMITEED:允许事务读取其它事务未提交的变更

READ COMMITED:(oracle 默认级别) 只允许事务读取已提交的变 更,避免读到其他事务没有提交的数据。

REPEATABLE_READ:(mysql默认级别)
在这个事务持续期间,禁止其他事务对这个字段进行修改,
避免不可重复读(一个事务读取数据之后操作期间,另一个事务对数据进行了修改,此时第一个事务读到的数据就出错了)

SERIALIZABLE: 这个事务持续期间,禁止其它事务对该表执行修改操作


hibernate 悲观锁-乐观锁

1>为什么要加锁:
Hibernate不设置的话默认是与数据库的事务隔离机制一致的。
如果数据库设置的隔离级别是READ COMMITED,为了避免不可重复 读的问题,就需要Hibernate造作事务时加锁。

2>悲观锁原理:
本质是通过sql语句的for update子句锁定了表中符合的记录.
本次提交事务之前,其他事务无法使用该数据.(相当于REPEATABLE_READ事务隔离)

//使用悲观锁示例
Account a = (Account)session.load(Account.class, 1, LockMode.UPGRADE);

缺点:锁住数据不让别人访问,对于需要高并发的访问的数据是不适用的

3>乐观锁原理:(解决了悲观锁的缺点)
实质上乐观锁并没有给数据加锁,其它事务还是可以使用该数据的。

乐观锁只是给数据添加了一个version字段作为标记,每个事务在对数据操作之后,这个version值就会自增1。

事务操作结束后,在提交事务时候就会检查这个标记字段的值,如果这个值与事务最初拿到的值相同,则认为其他事务没有对数据操作,可以提交事务。

否则,就认为其他事务对数据进行了操作,事务最初读到的数据已经失效,此时就会抛出 org.hibernate.TransactionException异常,提交事务失败。

//为Persons持久化数据添加乐观锁示例
1>给Persons数据表添加version字段
2>配置持久化类的配置文件(添加乐观锁)

<hibernate-mapping>
    <!--class添加乐观锁optimistic-lock="version"-->
    <class name="models.Person" table="person" catalog="mydatabase" optimistic-lock="version">
        <id name="pid" type="java.lang.Integer">
            <column name="pid" />
            <generator class="assigned" />
        </id>
        <!--添加version-->
        <versionname="version" column="VERSION"
        type="java.lang.Integer"/>

        <property name="pname" type="java.lang.String">
            <column name="pname" length="10" />
        </property>

        <property name="page" type="java.lang.Integer">
            <column name="page" />
        </property>

    </class>
</hibernate-mapping>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hibernate可以使用悲观锁乐观锁来控制多个线程同时访问同一条记录时的并发性问题。 实现悲观锁的方法是,在Hibernate的查询语句中使用“for update”语句,例如: ``` Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction(); try { Item item = (Item) session.get(Item.class, itemId, LockMode.UPGRADE); item.setPrice(newPrice); session.update(item); tx.commit(); } catch (Exception e) { tx.rollback(); throw e; } ``` 在这个例子中,我们使用了LockMode.UPGRADE参数来获取悲观锁,这会在数据库中将该行记录锁定,直到事务提交或回滚为止。 要实现乐观锁,可以使用Hibernate的@Version注解来定义一个版本号属性,例如: ``` @Entity public class Item { @Id private Long id; private String name; private double price; @Version private int version; // getters and setters } ``` 在使用乐观锁的代码中,我们首先获取实体对象,修改实体对象的属性值,然后执行更新操作,例如: ``` Session session = sessionFactory.getCurrentSession(); Transaction tx = session.beginTransaction(); try { Item item = (Item) session.get(Item.class, itemId); item.setPrice(newPrice); session.update(item); tx.commit(); } catch (StaleObjectStateException e) { tx.rollback(); throw new OptimisticLockException("The item has been updated by another transaction", e); } catch (Exception e) { tx.rollback(); throw e; } ``` 在这个例子中,如果在我们修改实体对象的属性值后,有另一个事务已经修改了该实体对象,那么我们就会捕获到StaleObjectStateException异常,这时我们就可以回滚事务并抛出一个OptimisticLockException异常,提示用户该实体对象已经被其他事务修改过了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值