hibernate中经常用到当多个人对同一数据同时进行修改的时候,会发生脏数据,造成数据的不一致性,解决办法是可以通过悲观锁和乐观锁来实现。
悲观锁:在数据有加载的时候就给其进行加锁,直到该锁被释放掉,其他用户才可以进行修改,
优点:数据的一致性保持得很好,缺点:不适合多个用户并发访问,依赖于数据库锁机制,
当一个锁住的资源不被释放掉的时候,这个资源永远不会被其他用户进行修改,容易造成无限期的等待。
乐观锁:来源于状态维护,通过对数据的状态列数据进行维持来实现。 在对数据进行修改的时候,对数据才去版本或者时间戳等方式来比较,数据是否一致性来实现加锁。
优点:对数据库无锁机制要求,能支持大并发数据,对长事务支持好。 缺点:因为乐观锁基于数据状态维持的,故对于系统有业务上的要求,有一定的局限性。
乐观锁实现:
<hibernate-mapping package="com.chinahometex.b2b.cms.entity.main">
<class name="CmsGroup" table="jc_group" dynamic-insert="true" optimistic-lock="version"> <!-- 打开乐观锁,确定使用版本类型乐观锁-->
<meta attribute="sync-DAO">false</meta>
<cache usage="read-write"/>
<id name="id" type="java.lang.Integer" column="group_id"><generator class="identity"/></id>
<version name="version" column="version" ></version> <!-- 使用乐观锁的列 -->
<property name="name" column="group_name" type="string" not-null="true" length="100" />
<property name="priority" column="priority" type="integer" not-null="true" length="10"/>
<property name="allowPerDay" column="allow_per_day" type="integer" not-null="true" length="10"/>
<property name="allowMaxFile" column="allow_max_file" type="integer" not-null="true" length="10"/>
<property name="allowSuffix" column="allow_suffix" type="string" not-null="false" length="255"/>
<property name="needCaptcha" column="need_captcha" type="java.lang.Boolean" not-null="true"/>
<property name="needCheck" column="need_check" type="java.lang.Boolean" not-null="true"/>
<property name="regDef" column="is_reg_def" type="java.lang.Boolean" not-null="true"/>
<set name="viewChannels" table="jc_chnl_group_view" inverse="true">
<cache usage="read-write"/>
<key column="group_id"/>
<many-to-many column="channel_id" class="Channel"/>
</set>
<set name="contriChannels" table="jc_chnl_group_contri" inverse="true">
<cache usage="read-write"/>
<key column="group_id"/>
<many-to-many column="channel_id" class="Channel"/>
</set>
<property name="jobPreSum" column="n_jobpersum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="jobSum" column="n_jobsum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="buyPreSum" column="n_buypersum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="buySum" column="n_buysum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="supplyPreSum" column="n_supplypersum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="supplySum" column="n_supplysum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="proxyPreSum" column="n_proxypersum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="proxySum" column="n_proxysum" type="java.lang.Integer" not-null="false" length="10"/>
<property name="logoPath" column="s_logo" type="java.lang.String" not-null="false" />
</class>
</hibernate-mapping>
悲观锁实现:
session.load(CmsGroup.class,1,LockMode.UPDATE);
或
Query query = sessoion.createQuery(hsql);
query.setLockMode(LockMode.UPGRAND);
悲观锁策略:
1. LockMode.NONE:无锁机制
2. LockMode.WRITE:Hibernate在Insert和Update记录的时候会自动获取
3. LockMode.READ:Hibernate在读取记录的时候会自动获取
4. LockMode.UPGRADE:利用数据库的for update子句加锁
5. LockMode.UPGRADE_NOWAIT:Oracle的特定实现,利用Oracle的for update nowait子句实现加锁
乐观锁策略:
1. none:无乐观锁
2. version:通过版本机制实现乐观锁
3. dirty:通过检查发生变动过的属性实现乐观锁
4. all:通过检查所有