1 乐观锁解析
每次读取数据时,不进行上锁;但是执行更新操作时,会判断在此期间有没有其他更新操作去更新这个数据。
2 实现
2.1 实现思想
乐观锁是基于数据版本( Version )来实现。数据版本,就是为数据增加的一个版本标识。当读取数据时,将版本标识的值一同读出,数据每更新一次,同时对版本标识进行更新。当我们提交更新的时候,判断数据库表对应记录的当前版本信息与第一次取出来的版本标识进行比对,如果数据库表当前版本号与第一次取出来的版本标识值相等,则予以更新;否则进行报错,不进行更新。
2.2 具体实现
1. 新建一个字段
1 |
`version` int(11) NOT NULL DEFAULT '1' COMMENT '版本号', |
2. mapper中设置
(1)新增
在mapper的insert语句中不包括version字段。只是在数据库字段中设置“ NOT NULL DEFAULT ‘1’”,这样默认初始化为1.
(2)更新
在mapper的xml中,对于更新操作如下
1 2 3 4 5 6 |
update tableName set ... version = #{version} + 1 where .. |
3. 代码中更新逻辑
将更改的entity中version,和数据库中version进行比较,如果不同就抛出异常。
3 举例
1. 建表
1 2 3 4 5 |
create table `student` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键', `name` varchar(50) NOT NULL COMMENT '名字' `version` int(11) NOT NULL DEFAULT '1' COMMENT '版本号' ) ENGINE=InnoDB AUTO_INCREMENT=750635 DEFAULT CHARSET=utf8mb4 COMMENT='测试乐观锁' |
2. 对应entiy
1 2 3 4 5 6 7 8 |
class StudentEntity{ int id; String name; int version; ...getter和seter方法.... } |
3. dao定义
1 2 3 4 |
public interface StudentDao(){ int insert(StudentEntity entity); int update(StudentEntity entity); } |
4. mapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<insert id="insert"> INSERT student ( name, ) VALUES ( #{name} ) </insert> <update id="insert"> update student set name = #{name}, version = #{version} + 1 </update> |
5 代码中判断version逻辑
1 2 3 4 5 6 7 8 9 |
public StudentService { public int updateStudent(StudentEntity entity){ // 1. 根据entity中id查询数据库得到一个referenceEntity // 2. 比较entity.getVersion和referenceEntity.getVersion是否一样,一样的话就执行更新操作,否则抛出异常 } } |
(全文完)