【MyBatis】第三篇:传递参数

news2024/11/26 8:58:55

前面聊了一些配置文件的标签意义,在实例演示的时候,发现用的sql都是定死的,也就是无法传递参数,这个不符合开发的环境的,毕竟程序是需要交互的,自然也会有参数传递,下面依次进行演示。

在映射文件中参数两种写法

前面实例可以看出mybatis其没有实现接口的类,而是通过配置映射文件进行实现,当然框架是通过反射解读XML而实现,所以如何在XML中实现参数呢?有两种写法。${}#{}

  • ${} :本质就是字符串拼接,拼接一个sql语句。如果是字符串,日期等需要添加单引号了。
  • #{}:本质是一个占位符,然后进行赋值。然后会自动将为参数两侧添加单引号。

还是先说理论,然后进行演示就明白其区别,或者说用发。

因为为了观察一下其运行是否带有单引号,所以需要用log4j这种第三方日志包更方便一些,所以通过maven的pom.xml添加包环境:

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

然后再添加一个log4j.properties文件

在这里插入图片描述

内容如下:

#日志输出到哪里
log4j.rootLogger=ALL,systemOut
 # 日志输出到控制台
log4j.appender.systemOut = org.apache.log4j.ConsoleAppender
log4j.appender.systemOut.layout = org.apache.log4j.PatternLayout
log4j.appender.systemOut.layout.ConversionPattern = [%-5p][%-22d{yyyy/MM/ddHH:mm:ssS}][%l]%n%m%n
log4j.appender.systemOut.Threshold = DEBUG
log4j.appender.systemOut.ImmediateFlush = TRUE
log4j.appender.systemOut.Target = System.out
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG

然后映射配置文件中如下些:

<?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.xzd.mapper.StudentMapper">
    <!--    这个配置文件id和 mapper类中的方法一样-->
 
    <select id="getStudentByName" resultType="com.xzd.domain.Student">
        <!-- 配置两个进演示 -->
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{sname}
   <!-- SELECT 	* FROM  testmybatis.student  WHERE SNAME=${sname} -->
    </select>
</mapper>

映射的接口:

package com.xzd.mapper;
import com.xzd.domain.Student;
public interface StudentMapper {
 
    Student getStudentByName(String sname);

}

Student这个对象类就不粘贴全部了,看图

在这里插入图片描述

核心配置文件:

<?xml version="1.0" encoding="utf-8"?>
<!--配置文件中可以使用哪些标签,这个地方是配置这是一个mybatis文件,使用mybatis文件标签-->
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<!--开始配置信息-->
<configuration>
    <properties resource="jdbc.properties"></properties>
<!--   是否配置日志 log4j-->
        <settings>
            <setting name="logImpl" value="LOG4J"/>
      </settings>
<!-- 是否因为jdbc等外部配置文件-->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>

            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.xzd.mapper" ></package>
    </mappers>
</configuration>

测试类:

public class Test_mabtis {
    @Test
    public void test1() throws IOException {
//         通过IO操作配置文件  所以说这个配置文件可以改名字,一般默认是mybatis-config.xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//        SqlSession类似与jdb中connection,但是其通过SqlSession工厂而创建的,而这个工厂却是通过工厂的构造类SqlSessionFactoryBuilder得到工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        返回SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
//        得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        这个通过代理模式,传入什么类返回什么类
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        System.out.println("#{}--------  "+result);
//      System.out.println("${}--------  "+result);
 
//        关闭sqlSession
        sqlSession.close();
    }
}
  • 首先打印使用#{}打印日志截图:

在这里插入图片描述

  • 首先打印使用${}打印日志截图:

    因为了演示不会自动添加单引号,故意用名字作为查询字段,所以会直接报错:

    在这里插入图片描述

如果修改如下:

   <select id="getStudentByName" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${sname}'
    </select>

在这里插入图片描述

可以看出没有问题了,而且也可以看出其直接是一个拼接好的sql语句。

一个参数

mybatis 3.5之前版本

其实上面的例子,已经演示了一个参数,但是为什么现在又要说一下单个参数呢?

现在将映射文件修改为:

   <select id="getStudentByName" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${value}'
    </select>

其它的不修改,可以看出传递的参数名为sname,但是我使用value,看一下结果:

在这里插入图片描述

似乎可以随意写参数名字,那如下测试呢?

<select id="getStudentByName" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${abc}'
    </select>

在这里插入图片描述

报错了,那么使用**#{}**呢?

<select id="getStudentByName" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{abc}
    </select>

在这里插入图片描述

这个却可以,然后#{value}也是上面结果,所以可以总结:

如果是一个参数,在映射文件中无论使用#{}。其中参数的名字,可以所以写都不会影响结果。比如实例中的使用value,也可以使用abc等等。 但是如果使用${}的话,只能使用类属性或者value

mybatis 3.5之后版本

这个就不一样了,#{}几乎一样,但是${}就一样了,如下演示:

 <select id="getStudentByName" resultType="com.xzd.domain.Student">
     <!--  估计两边不带有单引号,因为还有一点就是报错通过log4j输出的日志信息也不同 -->
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=${abc}
    </select>

在这里插入图片描述

可以看出如果在3.5版本之后,总结:

如果是一个参数的话,无论使用#{}或者${} 其中对参数可以任何字符代替比如使用类属性,value,甚至是abc等

两个以及以上参数

当然这个不同版本的效果也是不同,所以就以3.5之后的版本进行演示,然后说一下之前版本的一些不同,毕竟很多开发环境也是随着版本迭代而变化的。

mybatis3.5之后版本

现在进行如下尝试,首先根据一个参数的经验如此

接口类:

// 添加一个需要通过名字和Id查询的方法,当然一般id足以查询某条数据了,但是本篇主要聊参数如何传递,所以大家先忽略这些问题 
Student getStudentIdNAme(String sname,int id);

配置映射文件,添加:

    <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{sname} and SID= #{sid}
    </select>

然后调用测试类,可以看下如下报错信息:

在这里插入图片描述

直接告诉如何在映射文件中写参数了

然后如下尝试:

 <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{arg0} and SID= #{arg1}
    </select>

在这里插入图片描述

然后这样修改:

   <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{ param1} and SID= #{ param2}
    </select>

在这里插入图片描述

可以看出如果是通过arg开头是从0开始的,但是如果通过param开头是从1开始的。

为什么会这样,其实,mybatis在传递参数的时候,会将数据放在map中,其中一个情况是通过arg…为key,参数为值。第二种情况是以param…为key,然后参数为值。所以可以通过两个key获取相对应的值了。

在3.5版本之后,无论#{}还是 都可以通过上面规则得到结果。只不过 {}都可以通过上面规则得到结果。只不过 都可以通过上面规则得到结果。只不过{}需要添加单引号才行。

mybatis 3.5之前版本

这个又分两种情况,比如3.4.6版本和3.5版本没有什么区别,但是比如3.4.0版本的话,可以看其输出的错误信息:

在这里插入图片描述

可以直接通过数字来得到信息。但是这个数字只能使用在#{}中,如果使用在${}中,数字会直接变成条件值数字,而不是数字所代表的参数值,如下:

在这里插入图片描述

所以注意一下。在不同的版本的中的使用情况。

补充 如果传递的是map

上面说到mybatis会将多个传递参数变成一个map,那么直接传递一个参数map,然后进行调用如何?

现在进行演示:

import com.xzd.domain.Student;

import java.util.Map;
public interface StudentMapper {
 
    Student  getStudentByMap(Map<String,Object> map);

}

然后再映射文件中添加:

 <select id="getStudentByMap" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${sname}' and SID= '${sid}'
 </select>

然后再调用测试中如下:

public class Test_mabtis {
    @Test
    public void test1() throws IOException {
//         通过IO操作配置文件  所以说这个配置文件可以改名字,一般默认是mybatis-config.xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//        SqlSession类似与jdb中connection,但是其通过SqlSession工厂而创建的,而这个工厂却是通过工厂的构造类SqlSessionFactoryBuilder得到工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        返回SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
//        得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        这个通过代理模式,传入什么类返回什么类
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
        Map<String, Object> map=new HashMap<>();
        map.put("sname","张三");
        map.put("sid",1);
        Student result=studentMapper.getStudentByMap(map);
        System.out.println(" --------  "+result);
        sqlSession.close();
    }
 
}

看结果,没有问题。

在这里插入图片描述

可以看出也可以通过自定义一个map,进行传递,参数之间可以使用自己定义map的key。但是无法使用arg或者parm,因为会取不到值。

实验:

   <select id="getStudentByMap" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${arg0}' and SID= '${arg1}'
    </select>

在这里插入图片描述

补充传递的是一个对象

前面既然可以传递一个map,开发过程中也会传递一个对象,如果传递的是对象呢?现在试一下。

不过一般传递对象的时候是插入操作。可以如下

  <insert id="insertOne" >
        INSERT INTO `testmybatis`.`student` (`sid`, `sname`, `sage`, `ssex`)
        VALUES ('${sid}', '${sname}', '${sage}', '${ssex}');
    </insert>

映射类:

public interface StudentMapper {
    void insertOne(Student  student);
}

测试类:

public class Test_mabtis {
    @Test
    public void test1() throws IOException {
//         通过IO操作配置文件  所以说这个配置文件可以改名字,一般默认是mybatis-config.xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//        SqlSession类似与jdb中connection,但是其通过SqlSession工厂而创建的,而这个工厂却是通过工厂的构造类SqlSessionFactoryBuilder得到工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        返回SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
//        得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        这个通过代理模式,传入什么类返回什么类
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
          Student student=new Student(4,"宫崎",18,"男");
          studentMapper.insertOne(student);
        sqlSession.close();
    }
 
}

在这里插入图片描述

成功插入数据库中,可以查询数据库。

通过注解传递参数

还有一种方式,那就是通过注解传递,而这个注解才是开发过程中常用的一种方式:

@Param([value=]"重命名参数")

还是老规矩,来演示:

  <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
     <!-- 注解中故意写错,看如何报错  -->
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{abc} and SID= #{sid}
   </select>

在映射配置类中使用注解:

public interface StudentMapper {
     // 这事在形参前面使用@Param注解
    Student getStudentIdNAme(@Param("sname") String sname, @Param("sid") int sid);
 
}

测试类调用:

public class Test_mabtis {
    @Test
    public void test1() throws IOException {
//         通过IO操作配置文件  所以说这个配置文件可以改名字,一般默认是mybatis-config.xml
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//        SqlSession类似与jdb中connection,但是其通过SqlSession工厂而创建的,而这个工厂却是通过工厂的构造类SqlSessionFactoryBuilder得到工厂
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//        返回SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream);
//        得到SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        这个通过代理模式,传入什么类返回什么类
        StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);
         Student result =  studentMapper.getStudentIdNAme("张三",1);
        sqlSession.close();
    }
 
}

因为前面说了在注解中故意写错,看报错的的信息,所以得到报错信息如下:

在这里插入图片描述

可以看出,在映射文件中得到传递的参数值,可以通过@Param中修改的参数名得到,也可以通过param1这样得到,但是无法通过arg0这样得到了

  <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
     <!-- 注解中故意写错,看如何报错  -->
        SELECT 	* FROM  testmybatis.student  WHERE SNAME=#{sname} and SID= #{sid}
   </select>

在这里插入图片描述

或者

    <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${param1}' and SID= '${param1}'
    </select>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SvSSJyvs-1673871550840)(F:\文档\笔记\java\MyBatis\3:mybatis传递参数.assets\image-20230116201659766.png)]

但是如下:

    <select id="getStudentIdNAme" resultType="com.xzd.domain.Student">
        SELECT 	* FROM  testmybatis.student  WHERE SNAME='${arg0}' and SID= '${arg1}'
    </select>

在这里插入图片描述

就会出现报错。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/167310.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个注解(优雅)搞定SpringBoot项目中的身份证号、手机号等敏感数据脱敏

&#x1f4de; 文章简介&#xff1a;一个注解搞定身份证号、手机号等敏感数据脱敏处理 &#x1f4a1; 创作目的&#xff1a;公司中CRM的第一版快封版了&#xff0c;基本功能都落实了。接下来就是预防等保了&#xff0c;我负责的是核心业务客户模块这里自然有很多数据要做脱敏。…

【十 三】Netty 私有协议栈开发

Netty 私有协议栈开发私有协议介绍跨节点通信私有协议栈设计私有协议栈的网络拓扑图协议栈功能描述协议的通信模型消息体定义消息定义表私有协议消息头定义私有协议支持的字段类型私有协议的编解码规范私有协议的编码私有协议的解码链路的建立客户端握手请求握手请求消息定义服…

智能上线阻断的算法和实践

一、背景 上线是引起系统故障的主要原因之一&#xff0c;在有些公司甚至能占到故障原因的一半&#xff0c;及时地发现并阻断、回滚存在故障隐患的上线&#xff0c;可以有效地减少系统故障。 事实上&#xff0c;现在很多平台已经提供了基于手工配置规则来进行变更阻断的能力。…

Modern C++ | 谈谈万能引用以及它的衍生问题:将亡值、引用折叠和完美转发

文章目录前言左右值引用的铺垫万能引用&&引用折叠完美转发前言 在学习Linux系统编程的过程中&#xff0c;想着得到了新知识&#xff0c;不能把旧知识忘了啊&#xff0c;所以我就读起了以前写的博客&#xff0c;在Modern C介绍这篇博客中&#xff0c;关于完美转发只是介…

安科瑞智能仪表在密集母线行业中的应用

安科瑞 华楠AMB100智能母线监控系列系统示意图功能1.电压、电流、频率、有功功率、无功功率、功率因数、有功电能、无功电能、2-63次谐波、温度、湿度、漏电流等电参量测量&#xff1b;2.交流2DI、2DO&#xff0c;直流4DI、2DO&#xff1b;3.可信号取电或者独立辅助电源供电&am…

windows安装VMware最新版本(VMware Workstation 17.0 Pro)详细教程

目录 一、概述 二、下载 VMware Workstation 17.0 Pro 三、安装 VMware Workstation 17.0 Pro 四、创建一个空的虚拟机 一、概述 VMware Workstation Pro™ 是一个运行在window或Linux系统的软件&#xff0c;使开发人员能够在同一台 PC 上同时运行多个基于 x86 的 Windows、Li…

国内最全的Spring Boot系列之六

在新的一年祝大家兔年大吉&#xff0c;兔耳冲天&#xff0c;动如脱兔! 2022年就这么过去了&#xff0c;闭上眼回首2022年发生的事情&#xff0c;犹如过眼云烟 —— 一事无成的感觉。 2022年到底都发生了什么事情&#xff0c;坚持了什么&#xff1f;于是我闭上眼睛&#xff0c…

2023-1-16 刷题情况

子相似性 III 题目描述 一个句子是由一些单词与它们之间的单个空格组成&#xff0c;且句子的开头和结尾没有多余空格。比方说&#xff0c;“Hello World” &#xff0c;“HELLO” &#xff0c;“hello world hello world” 都是句子。每个单词都 只 包含大写和小写英文字母。…

K8s 如何通过 ConfigMap 来配置 Redis ?

1、创建 ConfigMap YAML 配置文件 cat <<EOF >./example-redis-config.yaml apiVersion: v1 kind: ConfigMap metadata:name: example-redis-config data:redis-config: "" EOF2、创建 ConfigMap 资源 kubectl apply -f example-redis-config.yaml创建完成…

VMware 已将该虚拟机配置为使用 64 位客户机操作系统。但是,无法执行 64 位操作的解决方法

在电脑上安装VMWare&#xff0c;运行虚拟机发现提示无法执行64位操作。本人系统是windows10,64位系统。错误提示&#xff1a; 已将该虚拟机配置为使用 64 位客户机操作系统。但是&#xff0c;无法执行 64 位操作。 此主机支持 Intel VT-x&#xff0c;但 Intel VT-x 处于禁用状态…

HTML的body元素

&#xff08;1&#xff09;HTML的body元素 body是一个简单的HTML稳定最基本的必需元素。 <body> 标签定义文档的主体。 <body> 元素包含文档的所有内容&#xff08;比如文本、超链接、图像、表格和列表等等&#xff09;。 &#xff08;2&#xff09;HTML 网页结…

HTML零基础教程,九大知识点带你玩转前端(上)

博主&#xff1a;冰小九&#xff0c;新人博主一只&#xff0c;欢迎大佬前来指导 冰小九的主页喜欢请给个三连加关注呀&#xff0c;谢谢&#x1f337;&#x1f337;&#x1f337;三连加关注&#xff0c;追文不迷路&#xff0c;你们的支持就是我最大的动力&#xff01;&#xff0…

【自学Docker 】Docker管理命令大全(上)

文章目录Docker create命令Docker create命令概述Docker create命令语法Docker create命令参数列表案例创建容器运行容器Docker create命令总结Docker exec命令Docker exec命令概述Docker exec命令语法Docker exec命令参数列表案例查看文件创建文件进入容器Docker exec命令总结…

Dubbo 自适应SPI

Dubbo 自适应SPI 1. 原理 在 Dubbo 中&#xff0c;很多拓展都是通过 SPI 机制进行加载的&#xff0c;比如 Protocol、Cluster、LoadBalance 等。有时&#xff0c;有些拓展并不想在框架启动阶段被加载&#xff0c;而是希望在拓展方法被调用时&#xff0c;根据运行时参数进行加…

录屏软件无水印免费,分享一款功能强大且免费的录屏软件

市面上多数录屏软件&#xff0c;只能试用版录制几分钟的视频&#xff0c;且带有水印。想要长时间录制电脑屏幕、录制无水印的录屏&#xff0c;需要解锁才可以。那有没有一款录屏软件试用版就能无水印&#xff1f;当然有啦。小编今天给大家分享一款不限制录制时长&#xff0c;且…

springboot整合Freemarker模板引擎

2.2 模板引擎 2.2.1 什么是模板引擎 根据前边的数据模型分析&#xff0c;课程预览就是把课程的相关信息进行整合&#xff0c;在课程预览界面进行展示&#xff0c;课程预览界面与课程发布的课程详情界面一致&#xff0c;保证了教学机构人员发布前看到什么样&#xff0c;发布后…

【Win11 + VSCode配置OpenCV C++一站式开发调试环境教程】

Win11 VSCode配置OpenCV C一站式开发调试环境教程1 下载1.1 版本介绍&#xff1a;1.2 对应三个软件的连接&#xff1a;2 环境配置3 编译1 下载 需要下载三个软件&#xff1a;OpenCV 、MInGW、CMake 1.1 版本介绍&#xff1a; 打开 OpenCV-MinGW-Build&#xff1a;OpenCV-4.…

Android启动流程源码分析(基于Android S)

从上图我们可以清楚的看到Android系统的启动分为以下几个步骤 启动电源以及启动系统 当我们按下电源键时, 引导芯片代码开始从预定义的地方(固化在ROM)开始执行, 加载引导程序到RAM, 然后执行 引导程序 引导程序是在Android操作系统开始运行前的一个小程序. 引导程序是运行的…

图片转PDF怎么弄?这几个方法值得你试一试

PDF是一种特殊的文件格式&#xff0c;它可以在任何设备和平台上进行传输&#xff0c;并且能够保证文件版式不被修改&#xff0c;此外&#xff0c;还可以兼容不同的系统&#xff0c;因为它的这些优势&#xff0c;大多数的人就喜欢将自己编辑好的WORD、PPT、EXCEL、图片等文件转换…

MySQL InnoDB的MVCC实现机制

MySQL InnoDB的MVCC实现机制1.MVCC概述2.MVCC的实现原理隐式字段undo日志Read View(读视图)RR隔离级别的Read View方案1.MVCC概述 什么是MVCC&#xff1f; MVCC&#xff0c;即多版本并发控制。MVCC是一种并发控制的方法&#xff0c;一般在数据库管理系统中&#xff0c;实现对…