MybatisPlus乐观锁











代码片段

java 复制代码
TestOneMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hk.mapper.TestOneMapper">
    <select id="query" resultType="com.hk.entity.TestOneInfo">
        select * from test_testone
    </select>
    <select id="queryList" resultType="com.hk.entity.TestOneInfo">
        select * from test_testone
        ${ew.customSqlSegment}
    </select>
</mapper>



TestOneInfo.java

package com.hk.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.Version;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;

import java.io.Serializable;
import java.util.Date;

@Data
@TableName("test_testone")
public class TestOneInfo implements Serializable{
	@TableId(type = IdType.ASSIGN_ID)
	private String id = null;
	private String name = null;
	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	private Date createTime = new Date();
	private String createId = null;
	@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	private Date updateTime = null;
	private String updateId = null;
	@Version
	private Long version = 0L;
}


TestOneMapper.java

package com.hk.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.hk.entity.TestOneInfo;
import org.apache.ibatis.annotations.Param;

public interface TestOneMapper extends BaseMapper<TestOneInfo> {
    public IPage<TestOneInfo> queryList(IPage<TestOneInfo> page ,
                                        @Param(Constants.WRAPPER) Wrapper<TestOneInfo> wrapper);
}


ITestOneService.java

package com.hk.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.hk.entity.TestOneInfo;
import com.hk.entity.TestTwoInfo;

public interface ITestOneService extends IService<TestOneInfo> {
    boolean save(TestOneInfo t);
    TestOneInfo get(String id) throws Exception;
    boolean delete(TestOneInfo t) throws Exception;
    boolean deleteById(String id) throws Exception;

    /**
     * 操作本表并通过Service操作第二张表,代码设置除0操作,检查两张表上的事务一致性
     * @return
     * @throws Exception
     */
    boolean testTx1() throws Exception;

    /**
     * testTx2,TestTx3分别操作表1和表2,它们同在一个Service实现类上
     * 检查两张表上的事务一致性
     * @return
     * @throws Exception
     */
    boolean testTx2(TestOneInfo t) throws Exception;
    boolean testTx3(TestTwoInfo t) throws Exception;

    /**
     * testTx4是公共方法,其中调用私有方法testTx5,两个方法分别操作两个表,
     * 代码抛出异常,检查两张表上的事务一致性
     * @param t
     * @return
     * @throws Exception
     */
    boolean testTx4(TestOneInfo t) throws Exception;

    /**
     * 根据数据库列定制Where条件,分页查询
     * @param pageNo 页码
     * @param pageSize 每页显示记录数
     * @param name 查询列
     * @param orderColumn 排序列
     * @param order 升序或降序,其值为CommonEnum.ASC或CommonEnum.DESC
     * @return
     * @throws Exception
     */
    IPage<TestOneInfo> queryName(Integer pageNo, Integer pageSize,String name,
                                    String orderColumn, String order)
            throws Exception;

    /**
     * 根据数据库列定制Where条件,分页查询Mapper中定义的方法
     * @param pageNo 页码
     * @param pageSize 每页显示记录数
     * @param orderColumn 排序列
     * @param order 升序或降序,其值为CommonEnum.ASC或CommonEnum.DESC
     * @param queryWrapper 查询条件封装类
     * @return
     * @throws Exception
     */
    IPage<TestOneInfo> queryMethod(Integer pageNo, Integer pageSize,
               String orderColumn, String order,
               QueryWrapper<TestOneInfo> queryWrapper)
            throws Exception;
}


TestOneServiceImpl.java

package com.hk.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hk.entity.TestOneInfo;
import com.hk.entity.TestTwoInfo;
import com.hk.mapper.TestOneMapper;
import com.hk.service.ITestOneService;
import com.hk.service.ITestTwoService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
@Transactional(readOnly=false,rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
public class TestOneServiceImpl extends ServiceImpl<TestOneMapper, TestOneInfo>
        implements ITestOneService
{
    @Autowired
    private ITestTwoService testTwoService;
    @Autowired
    private TestOneMapper testOneMapper;

    @Override
    public boolean save(TestOneInfo t) {
        try
        {
            return super.save(t);
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    @Override
    public TestOneInfo get(String id) throws Exception {
        try
        {
            return super.getById(id);
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    @Override
    public boolean delete(TestOneInfo t) throws Exception {
        try
        {
            return super.removeById(t.getId());
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    @Override
    public boolean deleteById(String id) throws Exception {
        try
        {
            return super.removeById(id);
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    /**
     * 测试回滚两个保存方法,其中一个方法是另外服务实例的方法
     * @return
     * @throws Exception
     */
    @Override
    public boolean testTx1() throws Exception {
        try
        {
            TestOneInfo one = new TestOneInfo();
            one.setId("1");
            one.setName("TestOne");
            save(one);
            TestTwoInfo two = new TestTwoInfo();
            two.setId("2");
            two.setName("TestTwo");
            testTwoService.save(two);
            int i=1/0;
            return false;
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    /**
     * 测试回滚两个保存方法,其中一个方法是调用另外服务实例中的方法
     * @param t
     * @return
     * @throws Exception
     */
    @Override
    public boolean testTx2(TestOneInfo t) throws Exception {
        try
        {
            save(t);
            TestTwoInfo two = new TestTwoInfo();
            two.setId("2");
            two.setName("TestTwo");
            testTx3(two);
            int i=1/0;
            return false;
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    @Override
    public boolean testTx3(TestTwoInfo t) throws Exception {
        try
        {
            testTwoService.save(t);
            return false;
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    /**
     * 测试回滚两个保存方法,其中一个方法是私有方法
     * @param t
     * @return
     * @throws Exception
     */
    @Override
    public boolean testTx4(TestOneInfo t) throws Exception {
        try
        {
            save(t);
            TestTwoInfo two = new TestTwoInfo();
            two.setId("2");
            two.setName("TestTwo");
            testTx5(two);
            int i=1/0;
            return false;
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    private boolean testTx5(TestTwoInfo t) throws Exception {
        try
        {
            testTwoService.save(t);
            return false;
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    @Override
    public IPage<TestOneInfo> queryName(Integer pageNo, Integer pageSize,
            String name, String orderColumn, String order) throws Exception
    {
        try
        {
            Page<TestOneInfo> p = new Page<TestOneInfo>(pageNo, pageSize);
            QueryWrapper wrapper = new QueryWrapper<TestOneInfo>();
            wrapper.like("name",name);
            return page(p,wrapper);
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

    @Override
    public IPage<TestOneInfo> queryMethod(Integer pageNo, Integer pageSize, String orderColumn, String order, QueryWrapper<TestOneInfo> queryWrapper) throws Exception {
        try
        {
            Page<TestOneInfo> p = new Page<TestOneInfo>(pageNo, pageSize);
            IPage<TestOneInfo> pageList = testOneMapper.queryList(p,queryWrapper);
            return pageList;
        }
        catch(Exception e)
        {
            log.error(e.getMessage(),e);
            throw e;
        }
    }

}


OptimisticLockTest.java

package com.hk.user;

import com.hk.Starter;
import com.hk.entity.TestOneInfo;
import com.hk.service.ITestOneService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.util.Assert;

import java.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,classes = Starter.class)
public class OptimisticLockTest {
    @Autowired
    private ITestOneService testOneServ;

    /**
     * 使用默认数据源,测试Mybatis乐观锁控制
     * @throws Exception
     */
    @Test
    public void testOptimisticLock() throws Exception {
        List<TestOneInfo> lst = testOneServ.list();
        for(TestOneInfo t:lst)
            testOneServ.delete(t);
        TestOneInfo one = new TestOneInfo();
        one.setId("1");
        one.setName("testone1");
        testOneServ.save(one);

        TestOneInfo saveOne = testOneServ.get("1");
        saveOne.setName("testone1-saveonce"+Math.random());
        testOneServ.saveOrUpdate(saveOne);
        //保存一次后检查版本是否变为1
        saveOne = testOneServ.get("1");
        System.out.println("saveOne.version========="+saveOne.getVersion());
        Assert.isTrue(saveOne.getVersion() == 1);

        //保存版本为0的对象,捕捉乐观锁异常
        try {
            //此时one版本为0,应该保存失败
            boolean b = testOneServ.saveOrUpdate(one);
            System.out.println("saveOne.b========="+b);
            Assert.isTrue(b,"数据记录版本冲突");
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
相关推荐
神仙别闹几秒前
基于 C# OpenPGP 的文件管理系统
开发语言·c#
番石榴AI16 分钟前
纯 CPU 推理!0.1B 超轻量级端到端OCR模型,使用 Java 进行文档解析
java·开发语言·ocr
likerhood20 分钟前
ConcurrentHashMap详细讲解(java)
java·开发语言·性能优化
机器学习之心34 分钟前
集成BWM法、熵权法、改进博弈论组合赋权与三角直觉模糊云模型的多属性评价模型,MATLAB代码
开发语言·matlab·熵权法·三角直觉模糊云模型·bwm法·改进博弈论组合赋权·多属性评价模型
特种加菲猫1 小时前
二叉搜索树:数据世界的“快速寻路指南”
开发语言·c++
特种加菲猫1 小时前
STL关联容器:Set/Multiset与Map/Multimap详解
开发语言·c++
我滴老baby1 小时前
0基础速通Python+AI|2026热门轻量化玩法全攻略:从入门到实战,3天搞定AI应用开发
开发语言·人工智能·python
源码集结号1 小时前
基于 Spring Boot + JPA + MySQL的上门家政系统代码示例
java·前端·后端
一个天蝎座 白勺 程序猿1 小时前
Python(29)Python生成器函数深度解析:asyncio事件循环的底层实现与异步编程实战
开发语言·python
2zcode1 小时前
原创文档:基于MATLAB的线性预测编码变声器系统
开发语言·matlab·语音识别