Hibernate乐观锁实现之Version

本文转载自http://esffor.iteye.com/blog/168243

通过在表中及POJO中增加一个version字段来表示记录的版本,来达到多用户同时更改一条数据的冲突

数据库脚本:

 

create  table studentVersion (id  varchar( 32),name  varchar( 32),ver  int);

POJO

 

package Version;

public  class Student {
   private String id;
   private String name;
   private  int version;
public String getId() {
     return id;
}
public  void setId(String id) {
     this.id = id;
}
public String getName() {
     return name;
}
public  void setName(String name) {
     this.name = name;
}
public  int getVersion() {
     return version;
}
public  void setVersion( int version) {
     this.version = version;
}


}

 

Student.hbm.xml

 

<? xml version="1.0" encoding="utf-8" ?>
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"
>
<!--  
    Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping >
< class  name ="Version.Student"  table ="studentVersion"   >
     < id  name ="id"  unsaved-value ="null" >
       < generator  class ="uuid.hex" ></ generator >
     </ id >
     <!-- version标签必须跟在id标签后面 -->
     < version  name ="version"  column ="ver"  type ="int" ></ version >
     < property  name ="name"  type ="string"  column ="name" ></ property >  
</ class >

</ hibernate-mapping >

 

Hibernate.cfg.xml

 

<? xml version='1.0' encoding='UTF-8' ?>
<! DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>

<!--  Generated by MyEclipse Hibernate Tools.                    -->
< hibernate-configuration >

< session-factory >
     < property  name ="connection.username" >root </ property >
     < property  name ="connection.url" >
        jdbc:mysql://localhost:3306/schoolproject?characterEncoding=gb2312 &amp;useUnicode=true
     </ property >
     < property  name ="dialect" >
        org.hibernate.dialect.MySQLDialect
     </ property >
     < property  name ="myeclipse.connection.profile" >mysql </ property >
     < property  name ="connection.password" >1234 </ property >
     < property  name ="connection.driver_class" >
        com.mysql.jdbc.Driver
     </ property >
     < property  name ="hibernate.dialect" >
        org.hibernate.dialect.MySQLDialect
     </ property >
     < property  name ="hibernate.show_sql" >true </ property >
     < property  name ="current_session_context_class" >thread </ property >
     < property  name ="jdbc.batch_size" >15 </ property >
     < mapping  resource ="Version/Student.hbm.xml"   />




</ session-factory >

</ hibernate-configuration >

 

测试代码:

 

package Version;


import java.io.File;
import java.util.Iterator;
import java.util.Set;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public  class Test {


     public  static  void main(String[] args) {

        String filePath=System.getProperty("user.dir")+File.separator+"src/Version"+File.separator+"hibernate.cfg.xml";
        File file= new File(filePath);
        System.out.println(filePath);
        SessionFactory sessionFactory= new Configuration().configure(file).buildSessionFactory();
        Session session=sessionFactory.openSession();
        Transaction t=session.beginTransaction();
        
        Student stu= new Student();
        stu.setName("tom11");
        session.save(stu);
        t.commit();
      
        
         /*
         * 模拟多个session操作student数据表
         
*/
        
        Session session1=sessionFactory.openSession();
        Session session2=sessionFactory.openSession();
        Student stu1=(Student)session1.createQuery("from Student s where s.name='tom11'").uniqueResult();
        Student stu2=(Student)session2.createQuery("from Student s where s.name='tom11'").uniqueResult();
        
         // 这时候,两个版本号是相同的
        System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());
        
        Transaction tx1=session1.beginTransaction();
        stu1.setName("session1");
        tx1.commit();
         // 这时候,两个版本号是不同的,其中一个的版本号递增了
        System.out.println("v1="+stu1.getVersion()+"--v2="+stu2.getVersion());
        
        Transaction tx2=session2.beginTransaction();
        stu2.setName("session2");
        tx2.commit();
        
        
        
    }

}

 

运行结果:

Hibernate: insert into studentVersion (ver, name, id) values (?, ?, ?)
Hibernate: select student0_.id as id0_, student0_.ver as ver0_, student0_.name as name0_ from studentVersion student0_ where student0_.name='tom11'
Hibernate: select student0_.id as id0_, student0_.ver as ver0_, student0_.name as name0_ from studentVersion student0_ where student0_.name='tom11'
v1=0--v2=0
Hibernate: update studentVersion set ver=?, name=? where id=? and ver=?
v1=1--v2=0
Hibernate: update studentVersion set ver=?, name=? where id=? and ver=?
Exception in thread "main" org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [Version.Student#4028818316cd6b460116cd6b50830001]

 

可以看到,第二个“用户”session2修改数据时候,记录的版本号已经被session1更新过了,所以抛出了红色的异常,我们可以在实际应用中处理这个异常,例如在处理中重新读取数据库中的数据,同时将目前的数据与数据库中的数据展示出来,让使用者有机会比较一下,或者设计程序自动读取新的数据

 

注意:如果手工设置stu.setVersion()自行更新版本以跳过检查,则这种乐观锁就会失效,应对方法可以将Student.java的setVersion设置成private

常用机器学习库和深度学习库整理 这一年多以来的科研工作中,调研了不少机器学习库的相关知识,临近年底,事情不多,感觉正好可以整理一下。由于笔者主要使用python的缘故,这里介绍的函数库以python库居多,但也顺带介绍了一些其他编程语言的机器学习库。 阅读详情

相关推荐

标准c++库和stl库,boost库,qt库的总结(一)

用了很长时间是stdio iostream 等头文件,一直有个疑惑,也用了很长一段是键的stl标准库中个别的类,间接性的知道了boost库,qt库等一系列的库 昨天在有用到#include头文件的时候,想起了istream ostream fstream这些类到底在c++标准中占什么位置,记得在大脑中一直将他们定性到c++标准库,有忽然想起了stl标准模板库里面各个分类里没有包含io这个类别的,

季风博客 8827

os 库、 sys 库、getopt 库 与 filecmp 库,5000 字长文带你搞定四大库

橡皮擦,一个逗趣的互联网高级网虫。新的系列,让我们一起 Be More Pythonic。 滚雪球学 Python 第二轮已完成的文章清单十四、sys 库、os 库、 getopt 库 与 filecmp 库14.1 os 库14.1.1 os 库路径操作14.1.2 os 库进程管理14.1.3 os 库运行环境相关参数14.2 sys 库14.2.1 常见属性如下14.2.2 常见方法如下14.3 getopt 库14.4 filecmp 库14.4.1 filecmp.cmp()、filecmp..

梦想橡皮擦,专栏100例写作模式先行者,现象级专栏 《Python 爬虫 100 例》作者、《滚雪球学 Python 专栏》原创者 2万+

c库、POSIX库、C++库、boost库之间的区别和联系

C 库函数:由 ANSI C 和 ISO C 标准定义,是 C 语言编程的基础组成部分,旨在为 C 语言提供通用的、基本的功能。POSIX:是 IEEE 制定的一系列标准,定义了操作系统与应用程序之间的接口规范,目标是让应用程序在不同操作系统上具有可移植性。Boost 库:由 C++ 社区开发和维护,是一个广泛使用的 C++ 库集合,提供了众多高质量、可移植且高效的库。C++ 标准库:由 ISO C++ 标准定义,是 C++ 语言的重要组成部分,随着 C++ 标准的不断更新而发展。

hs977986979的博客 890

hibernate 版本(version)控制

Hibernate支持乐观锁。当多个事务同时对数据库表中的同一条数据操作时,如果没有加锁机制的话,就会产生脏数据(duty data)。Hibernate有2种机制可以解决这个问题:乐观锁和悲观锁。这里我们只讨论乐观锁。       Hibernate乐观锁,能自动检测多个事务对同一条数据进行的操作,并根据先胜原则,提交第一个事务,其他的事务提交时则抛出org.hibernate.StaleOb

筚路蓝缕 以启山林 2029

常见分布式锁1:数据库的乐观锁+version

常见分布式锁之数据库的乐观锁+version

L'Étranger的博客 947

乐观锁version的使用

乐观锁version的使用

Liveforyourself的博客 2380

关于Hibernate基于version乐观锁

刚刚接触SSH框架,虽然可能这个框架已经比较过时了,但是个人认为,SSH作为一个成熟的框架,作为框架的入门还是可以的。 马马虎虎学完了Hibernate的基础,总结一点心得之类的。 学习Hibernate乐观锁时: 首先要知道为什么要用乐观锁。之所以要用乐观锁,就是为了避免脏数据。这很像数据库原理中的共享锁(读锁)和排它锁(写锁)。不管是乐观锁、共享锁、排它锁,其目的都是为了保证数据的一致...

浮生 1872

Hibernate乐观锁实现——Version

Hibernate乐观锁实现——Version

WYZSC的专栏 1291

什么是拖库,撞库和洗库

--------------------------2020-02-06-----------------------武汉加油!中国加油!-----------------------今年这个年是我们陪伴父母最多的一年吧-----平安胜意---------------------------------- 你知道拖库,撞库和洗库么? 什么是拖库(因为谐音,也经常被称作“脱裤”). 拖库这个行为现在...

upup 1万+

标准库、HAL库、LL库

以STMicroelectronics的STM32系列为例,标准外设库提供了一组函数,用于简化外设(如GPIO、USART、SPI等)的配置和操作。LL库(低层库)提供了对硬件外设的更底层的访问接口,允许开发者直接操作寄存器,但仍保留了一定的封装以简化常见操作。以STM32的HAL库为例,它封装了更多的硬件细节,提供了一致的接口来操作不同的外设。:需要开发者具备更强的硬件知识,虽然代码复杂,但性能和灵活性最优,适合对性能要求高的应用。,你只需掌握基础操作,很多细节是自动处理的,适合入门和简单应用。

weixin_61944480的博客 4034

Python 常用内置库 time库、random库、turtle库

输出:time.struct_time(tm_year=2024, tm_mon=3, tm_mday=31, tm_hour=18, tm_min=30, tm_sec=48, tm_wday=6, tm_yday=91, tm_isdst=0)trutle(海龟)是python中的内置的一个标准模块,它提供了绘制线、圆和其他形状的函数,使用该模块可创建图形窗口,在图形窗口中通过简单重复动作直观地绘制界面和图形。输出:Sun,31 Mar 2024 18:31:56。

笨笨轻松熊的博客 2088

HAL库是什么,HAL库的定义

HAL是 Hardware Abstraction Layer 的缩写,中文名:硬件抽象层。HAL 库是 ST 为 STM32 最新推出的。

weixin_62488241的博客 1万+

SDL库及SDL_draw库的安装、SDL库的使用

在Ubuntu下使用apt-get安装,由于我在安装过程中出现的错误,要注意一定要在联网的情况下进行安装。分别安装libsdl1.2-dev、libsdl-image1.2-dev、libsdl-mixer1.2-dev、libsdl-ttf2.0-dev、libsdl-gfx1.2-dev。安装完成以后就会生成一个目录,在目录/usr/include下可以使用ls命令查看SDL文件夹中的内容,里面包含了所需要的头文件。

weixin_43824515的博客 3897

【MCU】寄存器、标准库、HAL库、LL库,这么多库!你叫我怎么选?

1、聊一聊 今天跟大家推荐一首非常暖心的歌曲<What Are Words>,一首歌曲的灵魂并不是歌曲本身,而是歌曲后面的故事,"或许喜欢这首歌,却心疼这个故...

最后一个bug的博客 5217

Python库:time库

一、time库简介 time库是Python中处理时间的标准库 计算机时间的表达 提供获取系统时间并格式化输出功能 提供系统级精确计时功能,用于程序性能分析 引入:import time time.<b>() 二、time库的使用 time库包括三类函数: 时间获取:time(),ctime(),gmtime() 时间格式化:strftime(),strptime() 程序计时:sleep(),perf_counter() 三、时间获取函数 time():获取当前

weixin_47008635的博客 8906

C++ Boost库:windows下编译Boost库

文章目录1. 需要编译的boost库2. 编译步骤3. 库命名规则4. VS配置库目录 1. 需要编译的boost库 通过bjam --show-libraries查看那些库需要编译: D:\Project\VisualStudioProjects\boost_1_67_0>bjam --show-libraries The following libraries require building: - atomic - chrono - container - con

超级大洋葱的博客 1万+

turtle 库

1.turtle库概述 turttle(海龟)库是turtle绘图体系python的实现。 turtle :1969年诞生,作用:程序设计入门 turtle库是python的标准库之一,入门级别的图形绘制函数 python 计算生态=标准库+第三方库 标准库:解释器直接安装到操作系统中的功能模块。 第三方库:经过安装后才能使用的功能模块 库:library 包:package 模块:module 统称为模块 turtle库运行原理 原理:有一只海龟通过从程序控制,自由改变颜色,方向宽度在窗

weixin_62816287的博客 1万+

什么是撞库攻击,如何预防撞库攻击?

1. 撞库的原理和危害 “撞库”(Credential Stuffing Attack)在网络安全中是一个古老的概念,按中文的字面意思解读,就是“碰撞数据库”的意思。“碰撞”意味着碰运气,即不一定能成功;而“数据库”中往往存储着大量敏感数据,比如我们登录一个网站所需要的用户名、密码,再比如手机号、身份证号等个人隐私信息。“撞库”在英文中的表述为 Credential Stuffing(密码嗅探),也非常直白的说明了撞库的主要场景:试图获取正确的账号/密码组合,大白话就是“盗号”。 现实中发生的撞库攻击主要是

weixin_46641057的博客 3万+
上一篇: OpenI入门-自己动手new一个Project
下一篇: Hibernate乐观锁实现之Timestamp
iteye_16431
博客等级 码龄8年 0粉丝 6原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值