小付博客

无话可说...

您现在的位置是:首页>技术分享>Hibernate的悲观锁和乐观锁

Hibernate的悲观锁和乐观锁

发布时间:2017-06-07 编辑:小付 浏览(574) 评论(0)

    谈到悲观锁和乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高并发性就越差
    并发性:
    当前系统进行了序列化后,你读取数据库后,别人查询不了,称为并发性不好

    1.悲观锁

    具有排它性(我锁住当前数据后,比人看不到此数据),悲观锁一般是由数据库机制来做到的

    悲观锁的实现:

    通常依赖于数据库机制,在整修过程中将数据库锁定,其它任何用户都不能读取或修改

    悲观锁的适用场景:

    悲观锁一般适合短事物比较多(如某一个数据取出后加1,立即释放)



    用户1,用户2同时读取到数据,但是用户2先-200,这时数据库里的是800,现在用户1也开始-200,可以用户1刚才读取到的数据是1000,现在用户用刚一开始读取的数据1000-200,而用户1在更新时数据库里的数据是800,按理说用户1应该是800-200=600,这样就造成更新丢失。这种情况下可采用两种方式解决:悲观锁、乐观锁。
    悲观锁:用户1读取数据后,用锁将其读取的数据锁上,这时用户2是读取不到数据的,只有用户1释放锁后用户2才可以读取,同样用户2读取数据的数据也锁上,这样就可以解决更新丢失了。

    实体类:

    public class Inventory {  
        private int itemNo;   
        private String itemName;      
        private int quantity;  
        public int getItemNo() {  
            return itemNo;  
        }  
        public void setItemNo(int itemNo) {  
            this.itemNo = itemNo;  
        }  
        public String getItemName() {  
            return itemName;  
        }  
        public void setItemName(String itemName) {  
            this.itemName = itemName;  
        }  
        public int getQuantity() {  
            return quantity;  
        }  
        public void setQuantity(int quantity) {  
            this.quantity = quantity;  
        }     
    }

    映射文件:

    <hibernate-mapping>  
        <class name="com.cn.hibernate.Inventory" table="t_inventory">  
            <id name="itemNo">  
                <generator class="native"/>  
            </id>  
            <property name="itemName"/>  
            <property name="quantity"/>  
        </class>  
    </hibernate-mapping>

    悲观锁的使用:

    如果要使用悲观锁,肯定在加载数据时就要锁住,通常采用for update语句

    hibernate使用load进行悲观锁加载


    Session.load(Class arg(),Serializable arg1,LockMode arg2)throws HibernateException

    LockMode:悲观锁模式(一般使用LockMode.UPGRADE)

    session = HibernateUtils.getSession();  
                tx = session.beginTransaction();  
                Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);  
                System.out.println(inv.getItemName());  
                inv.setQuantity(inv.getQuantity()-200);  
                  
                session.update(inv);  
                tx.commit();

    如果使用悲观锁,那么lazy(懒加载)无效



    2.乐观锁

    乐观锁:不是锁,是一种冲突检测机制,乐观锁的并发性较好,因为我改的时候,别人可随便修改乐观锁的实现方式:常用的是版本的方式(每个数据表中有一个版本字段version,某一个用户更新数据库后,版本号+1,另一个用户修改后再+1,当用户更新发现数据库当前版本号与读取数据时版本号不一致,等于或小于数据库版本号则更新不了)

    Hibernate使用乐观锁需要在映射文件中配置才可生效

    实体类

    public class Inventory {  
        private int itemNo;   
        private String itemName;      
        private int quantity;     
        private int version;//Hibernate用户实现版本方式乐观锁,但需要在映射文件中配置  
        public int getItemNo() {  
            return itemNo;  
        }  
        public void setItemNo(int itemNo) {  
            this.itemNo = itemNo;  
        }  
        public String getItemName() {  
            return itemName;  
        }  
        public void setItemName(String itemName) {  
            this.itemName = itemName;  
        }  
        public int getQuantity() {  
            return quantity;  
        }  
        public void setQuantity(int quantity) {  
            this.quantity = quantity;  
        }  
        public int getVersion() {  
            return version;  
        }  
        public void setVersion(int version) {  
            this.version = version;  
        }  
    }
     <!--version标签必须跟在id标签后面-->
        <version name="version" column="ver" type="int"></version>


关键字词:Hibernate,悲观锁,乐观锁