mybatis plus 分页+乐观锁 +多租户

mybatis plus代码生成请参考:https://blog.csdn.net/qq_35573689/article/details/105828867

mybatis plus 需要引入依赖:

        
		
			org.mybatis.spring.boot
			mybatis-spring-boot-starter
			2.1.0
		
		
		
			com.baomidou
			mybatis-plus-boot-starter
			3.2.0
		
		
			com.baomidou
			mybatis-plus-extension
			3.2.0
		

 

mybatis plus分页:

                    

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {


    /**
     * 分页插件,没有这个的话,属性total会为0,配置上就可以赋上值
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /**
     * mybatis plus 乐观锁插件配置,配置会生效
     */

    @Bean
    public OptimisticLockerInterceptor optimisticLoker(){
        return new OptimisticLockerInterceptor();
    }

}
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.wxj.bootmq.genecode.bo.Course;
import com.wxj.bootmq.genecode.dao.CourseMapper;
import com.wxj.bootmq.genecode.service.CourseService;
import com.wxj.bootmq.myannotion.resannotion.annotion.RestApi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;

/**
 * 

* 前端控制器 *

* * @author wxj * @since 2020-04-26 * mybatis 两种分页,一种是物理分页,一种是逻辑分页(内存分页) * */ @RestController @RequestMapping("/mybatisplus") public class CourseController { @Autowired private CourseService courseService; @Autowired private CourseMapper courseMapper; /** * mybatis plus物理分页 */ @GetMapping("/courseTruePage") @RestApi public IPage getCoursePage(){ QueryWrapper queryWrapper = new QueryWrapper<>(); Page page = new Page<>(1,5); IPage iPage = courseMapper.selectPage(page, queryWrapper); System.out.println("查询到的结果数为:"+iPage.getRecords().size()); int size = iPage.getRecords().size(); return iPage; } }

 

mybatis plus update:

updateById就不解释了,演示一下update(Obect object,Wrapper wrapper)方法(非全字段更新,全字段更新比较简单不说明):

@RestController
@RequestMapping("/score")
public class ScoreController {

    @Autowired
    ScoreMapper scoreMapper;

    @GetMapping("/myscore")
    public  IPage getScore(){
        Page page =  new Page<>(1,5);
        IPage page1 = scoreMapper.selectPage(page, null);
        return page1;
    }

    /**
     * 更新score,验证乐观锁@version的作用
     */
    @PutMapping("/myscore1")
    public void updateScore(@RequestBody Score score) throws InterruptedException {
        UpdateWrapper updateWrapper =  new UpdateWrapper<>();
        /**
         *  第一种更新写法
         *  下面这种写法会全字段更新 UPDATE score SET score=?, stu_id=?, course_id=?, score=? WHERE (stu_id = ? AND course_id = ?)
         */

        //updateWrapper.set("score",score.getScore()).eq("stu_id",score.getStuId()).eq("course_id",score.getCourseId());
        //int update = scoreMapper.update(score, updateWrapper);
        /**
         * 第二种写法
         * UPDATE score SET score=? WHERE (stu_id = ? AND course_id = ?)
         */
       /* updateWrapper.eq("stu_id",score.getStuId()).eq("course_id",score.getCourseId());
        Score tempScore =  new Score();
        tempScore.setScore(score.getScore());
        int update = scoreMapper.update(tempScore, updateWrapper);*/

        /**
         * 第三种写法
         *
         */
        LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(Score::getStuId,score.getStuId()).eq(Score::getCourseId,score.getCourseId());

         //UPDATE score SET score=?, stu_id=?, course_id=? WHERE (stu_id = ? AND course_id = ?)
        //int update = scoreMapper.update(score, lambdaUpdateWrapper);

        Score score1 = new Score();
        score1.setScore(score.getScore());
        //UPDATE score SET score=? WHERE (stu_id = ? AND course_id = ?)
        int update = scoreMapper.update(score1, lambdaUpdateWrapper);

        System.out.println("更新分数后结果是"+update);
    }


}

 

 

mybatis plus 乐观锁:

                  

  /**
     * mybatis plus 乐观锁插件配置,配置会生效
     */

    @Bean
    public OptimisticLockerInterceptor optimisticLoker(){
        return new OptimisticLockerInterceptor();
    }

 字段上使用@Version  支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
//@ApiModel(value="Score对象", description="")
public class Score implements Serializable {

    private static final long serialVersionUID=1L;

    private String stuId;

    private String courseId;

    private Integer score;
    @Version
    private Integer version;


}

 

在上面update代码打断点或者在线程休眠的时候去修改数据库值,修改数据会失败。此外不要尝试把业务字段作为乐观锁,比如我原来想把score最为业务字段修改,结果第一次可以修改成功,后面就会有问题

 

mybatis plus 多租户:

        什么是多租户——多租户是一种系统架构技术,在多个系统用户同时使用并保持数据隔离。简单说就是,多个系统或者多个用户例如不同的医院对接了同一个平台,这些医院的业务可以使用相同的表,用一个标识来分离/隔离数据。

       数据隔离三种方案和优缺点:

      独立数据库:为每个用户提供一个数据库,数据库隔离级别高,安全性好,但是很明显成本高,维护成本也高

     共享数据库、隔离数据架构:多个用户使用同一个数据库,但是每个租户对应一个Schema(数据库user)

     共享数据库、共享数据架构:使用相同数据库并使用同一个schema,只需要在业务表中配合添加租户Id字段。共享数据程度最高。

 mybatis plus 为我们提供了第三种数据隔离的简单实现方法:


import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantSqlParser;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Configuration
public class MybatisPlusConfig {


    /**
     * 分页插件,没有这个的话,属性total会为0,配置上就可以赋上值
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        //分页只需要用到下面的返回
        //return new PaginationInterceptor();

        /**
         * 配置租户先关内容
         */
        //创建分页插件
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();

        //创建sql解析器集合
        List sqlParserList = new ArrayList<>();
        //创建租户sql解析器
        TenantSqlParser tenantSqlParser = new TenantSqlParser();
        //设置租户处理器
        tenantSqlParser.setTenantHandler(new TenantHandler() {
            @Override
            public Expression getTenantId(boolean where) {
               //设置当前租户id,项目中可能是从前端传入,获取从缓存或cookie中获取
                return new StringValue("wxj");
            }

            @Override
            public String getTenantIdColumn() {
                //tenant_id 是数据库租户字段
                return "tenant_id";
            }

            @Override
            public boolean doTableFilter(String tableName) {
                //是否需要过滤某一张表
               /* List tableNameList = Arrays.asList("stu");
                if(tableNameList.contains(tableName)){
                    return true;
                }*/
                return false;
            }
        });

        sqlParserList.add(tenantSqlParser);
        paginationInterceptor.setSqlParserList(sqlParserList);

        return paginationInterceptor;

    }

    /**
     * mybatis plus 乐观锁插件配置,配置会生效
     */

    @Bean
    public OptimisticLockerInterceptor optimisticLoker(){
        return new OptimisticLockerInterceptor();
    }

}

在数据库表中添加上字段tenant_id,否则查询的时候会报错。到现在所有表的查询都会根据租户id查询。但是有些表我们是不需要进行过滤的,所以要进行排除。可以在Mapper类上或者方法上加上注解@SqlParser(filter = true)即可。例如:

@SqlParser(filter = true)
public interface CourseMapper extends BaseMapper {

}

 

你可能感兴趣的:(代码开发)