当前位置: 首页 > news >正文

myBatis-plus自动填充插件

在 MyBatis-Plus 3.x 中,自动填充的插件方式发生了变化。现在推荐使用 MetaObjectHandler 接口的实现类来定义字段的填充逻辑。以下是使用 MyBatis-Plus 3.x 自动填充的基本步骤:

1.基本配置

1.1添加 Maven 依赖:

确保你的 Maven 依赖中使用的是 MyBatis-Plus 3.x 版本。

<dependencies><!-- MyBatis-Plus 核心依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>最新版本</version></dependency><!-- 其他依赖... -->
</dependencies>

1.2 配置 MyBatis-Plus 自动填充

1.2.1使用@Component注解

创建一个实现 MetaObjectHandler 接口的配置类,用于定义字段填充逻辑。

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}
}

这种方式是 MyBatis-Plus 3.x 中推荐的字段自动填充方式。在这个示例中,MyMetaObjectHandler 类上添加了 @Component 注解,确保 Spring Boot 能够自动扫描到并注册为 Bean。这样,MyBatis-Plus 在执行插入和更新操作时会自动调用 MetaObjectHandler 中的对应方法进行字段填充

1.2.1 使用@Bean+@Configuration注解

当然也可以使用@bean的方式在mybatisConfig里面注入


import com.sky.handler.MyMetaObjectHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {@Beanpublic MyMetaObjectHandler myMetaObjectHandler() {return new MyMetaObjectHandler();}
}
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入时自动填充");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新时自动填充");this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}
}

但是用这种方式的时候需要注意MyMetaObjectHandler这个类前面不能加Component,否则会造成bean冲突。

定义实体类:
在实体类中定义需要自动填充的字段:

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.time.LocalDateTime;@Data
@TableName("your_table_name")
public class YourEntity {@TableIdprivate Long id;private String name;// 其他字段省略...// createTime 和 updateTime 字段将由 MyBatis-Plus 自动填充@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}

确保你的实体类中的字段类型和配置的 MetaObjectHandler 中的类型一致。

这样达到的实际效果就是

我们在封装好入库的对象的时候,没有setUpdateTime这个属性,那么执行intsert 和 update操作的之后,数据库中也会向UpdateTime存入值。

下面我们需要对一些细节说明一下

2. 严格模式与非严格模式

this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());

在这个示例中,MyMetaObjectHandler 实现了 MetaObjectHandler 接口,并在 insertFill 和 updateFill 方法中定义了字段填充的逻辑。strictInsertFill 和 strictUpdateFill 方法用于严格模式的字段填充。

非严格模式: 在非严格模式下,字段填充通常会在任何情况下都执行,即使字段的值已经被手动设置或者数据库中已经有了一个值。这样可能导致字段值被多次更新,。

严格模式: 相比之下,严格模式会更加谨慎。在严格模式下,字段填充只会在满足一定条件的情况下才执行。例如,在插入操作时,只有在字段的值为 null 时才会进行填充。在更新操作时,只有在字段的值为 null 或者被标记为需要更新时才会进行填充。

3.自动插入的时机

上述的自动填充操作是发生在数据库层面的

具体说是在 MyBatis 执行 SQL 语句时,MyBatis-Plus 框架会拦截这些 SQL 操作,根据配置的自动填充规则来动态生成相应的字段值,然后执行相应的 SQL 操作。这样可以在数据库层面确保这些字段的值符合预期。

插入操作: 当执行插入 SQL 语句时,MyBatis-Plus 拦截器会在插入前执行 MetaObjectHandler 的 insertFill 方法,填充相应字段的值,然后将填充后的 SQL 语句发送给数据库执行。

更新操作: 同理,对于更新 SQL 语句,MyBatis-Plus 会在更新前执行 MetaObjectHandler 的 updateFill 方法,填充相应字段的值,然后将填充后的 SQL 语句发送给数据库执行。

这样做的好处是在数据库层面确保了字段填充的一致性,避免了手动在 Service 层面或者 Controller 层面进行填充,减少了代码冗余和错误的可能性。这也是 MyBatis-Plus 提供的一种便捷的开发方式,使得开发者可以更专注于业务逻辑而不用过多关心数据库层面的操作。

注意:上述操作并不是废话,我们来看这样一个例子(这个例子是我实际项目中的例子,我们只需要关注自动填充相关的部分就可以)

实体类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("employee")
public class Employee implements Serializable {private static final long serialVersionUID = 1L;@TableId(type = IdType.AUTO)//自增主键private Long id;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String username;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String name;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String password;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String phone;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)@EnumValue()private String sex;@TableField(value = "id_number",insertStrategy = FieldStrategy.NOT_NULL)private String idNumber;private EmployeeStatus status;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@TableField(fill = FieldFill.INSERT)//表示该字段只会在插入的填充private LocalDateTime createTime;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@TableField(fill = FieldFill.INSERT_UPDATE)//表示这个字段只会在传入和更改的时候都会填充private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)//表示该字段只会在插入的填充private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)//表示该字段只会在插入的填充private Long updateUser;
}}

我的自动填充是这样写的

@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入时自动填充");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class,LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新时自动填充");this.strictUpdateFill(metaObject, "updateTime",LocalDateTime.class, LocalDateTime.of(2022,12,30,5,6,0));}
}

我这里写了一个测试类

@SpringBootTest
class SkyApplicationTest {@ResourceEmployeeMapper employeeMapper;@Testpublic  void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getPhone,"2222222222");Employee employee  = new Employee();employee.setPhone("111111111");employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println("");}}

那么这个sql执行的结果是什么?

UPDATEemployee SETphone='111111111',update_time='2022-12-30T05:06',update_user=null,phone='2222222222' WHERE(name = '张三');

这个sql为什么是这样的

我们先看phone这个字段
phone这个字段是没有设置自动填充的,但是两个入参,实体类Employee,和更新条件LambdaUpdateWrapper都对phone都对phone设置了值。
通过sql我们不难发现,mybatis-plus会先根据实体类中不为null的值进行set,然后再写入更新条件中的set
所以,最后更新到数据库里,谁写在SQL语句的最后,数据库里的值就会是谁。

下面

        update_time='2022-12-30T05:06',update_user=null,

这两个字段都是自动填充设置的,其中update_time=‘2022-12-30T05:06’,是我设置了固定值,而update_user=null,是因为我没在MyMetaObjectHandler里设置值的原因,才会赋值为null.

那么现在的问题是自动插入的时机在哪呢?

我们不妨构建这样的例子

 @Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入时自动填充");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,"updateUser",Long.class,1L);this.strictInsertFill(metaObject,"createUser",Long.class,1L);}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新时自动填充");this.strictUpdateFill(metaObject, "updateTime",LocalDateTime.class, LocalDateTime.of(2022,12,30,5,6,0));this.strictInsertFill(metaObject,"updateUser",Long.class,1L);}

自动填充的时候,uptdateUser会被填入1L

@Testpublic  void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);Employee employee  = new Employee();employee.setUpdateUser(3L);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println("");}

而在测试类中。实体类Employee中的updateUser值是3L
查询条件中的updateUser是2L

那么形成的SQL是什么样的呢?

/*17 2023-12-17 16:52:32   */UPDATEemployee SETupdate_time='2022-12-30T05:06',update_user=3,update_user=2 WHERE(name = '张三');

先update_user = 3,后update_user = 2,这个之前就解释过了
但是update = 1怎么没有呢?

这是因为前面说的我们在设置自动填充时遵循的时严格模式的插入,当执行update操作的时候,如果该实体类中的updat_user不为null,就不会触发字段填充。

严格模式下的填充规则
插入时填充规则(INSERT):

当执行插入操作时,只有在实体类的字段的值为 null 时才进行填充。
如果实体类字段的值不为 null,则填充操作会被忽略。
更新时填充规则(UPDATE):

当执行更新操作时,只有在字段的值为 null 或者字段被标记为需要更新时才进行填充。
如果字段的值不为 null,且字段没有被标记为需要更新,填充操作会被忽略。

一定一定注意,是实体类中的字段值为null

我们将测试类更改一下:


@SpringBootTest
class SkyApplicationTest {@ResourceEmployeeMapper employeeMapper;@Testpublic  void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);Employee employee  = new Employee();
//        employee.setUpdateUser(3L);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println("");}}

我们将实体类中updateUser设置为null

你会发现生成的SQL语言是

    UPDATEemployee SETupdate_time='2022-12-30T05:06',update_user=1,update_user=2 WHERE(name = '张三');

会发现,自动填充是触发了的。
并且在lambdaUpdateWrapper这个更新条件的前面。这是因为本质上,自动填充是给实体类的update_time赋值的。

此外还有一个注意点,有一种情况也会导致自动填充失效。

在mybatispluss的官网也有说明。
https://baomidou.com/pages/4c6bcf/
在这里插入图片描述

看下面这个例子

@SpringBootTest
class SkyApplicationTest {@ResourceEmployeeMapper employeeMapper;@Testpublic  void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);//        Employee employee  = new Employee();
//        employee.setUpdateUser(3L);employeeMapper.update(null,lambdaUpdateWrapper);System.out.println("");}}

他的sql实际为

UPDATEemployee SETupdate_user=2 WHERE(name = '张三');

之所以会这样,update的实体类入参是null,自动填充根本就没有启动。

所以当我们的实体类在定义的时候使用了@TableField(fill = FieldFill.*****)的时候,使用mybatis-plus自带的update方法的时候一定不能传null的实体类。可以传new my_entity()过来。

相关文章:

myBatis-plus自动填充插件

在 MyBatis-Plus 3.x 中&#xff0c;自动填充的插件方式发生了变化。现在推荐使用 MetaObjectHandler 接口的实现类来定义字段的填充逻辑。以下是使用 MyBatis-Plus 3.x 自动填充的基本步骤&#xff1a; 1.基本配置 1.1添加 Maven 依赖&#xff1a; 确保你的 Maven 依赖中使…...

746. 使用最小花费爬楼梯 --力扣 --JAVA

题目 给你一个整数数组 cost &#xff0c;其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用&#xff0c;即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的最低花费。 解题思路 到…...

使用Verdaccio搭建私有npm仓库

搭建团队的私有仓库&#xff0c;保证团队组件的安全维护和私密性&#xff0c;是进阶前端开发主管路上&#xff0c;必不可少的一项技能。 一、原理 我们平时使用npm publish进行发布时&#xff0c;上传的仓库默认地址是npm&#xff0c;通过Verdaccio工具在本地新建一个仓库地址…...

87 GB 模型种子,GPT-4 缩小版,超越ChatGPT3.5,多平台在线体验

瞬间爆火的Mixtral 8x7B 大家好&#xff0c;我是老章 最近风头最盛的大模型当属Mistral AI 发布的Mixtral 8x7B了&#xff0c;火爆程度压过Google的Gemini。 缘起是MistralAI二话不说&#xff0c;直接在其推特账号上甩出了一个87GB的种子 随后Mixtral公布了模型的一些细节&am…...

Golang 数组 移除元素 双指针法 leetcode27 小记

文章目录 移除元素 leetcode27暴力解法双指针法1. 快慢指针2. 双向指针 移除元素 leetcode27 go中数据类型的分类&#xff1a; 1.值类型&#xff1a;int、float、bool、string、数组、结构体 2.引用类型&#xff1a;指针、切片、map、管道、接口 由于切片为引用类型&#xff0c…...

c# OpenCV 图像裁剪、调整大小、旋转、透视(三)

图像裁剪、调整大小、旋转、透视图像处理基本操作。 croppedImage 图像裁剪Cv2.Resize() 调整图像大小图像旋转 Cv2.Rotate()旋转Cv2.Flip()翻转Cv2.WarpAffine()任意角度旋转Cv2.GetAffineTransform()透视 一、图像裁剪 // 读取原始图像 Mat image new Mat("1.png&q…...

Kafka相关知识

一、kafka架构 Kafka基础知识 Kafka是最初由Linkedin公司开发&#xff0c;是一个分布式、分区的、多副本的、多生产者、多订阅者&#xff0c;基于zookeeper协 调的分布式日志系统(也可以当做MQ系统)&#xff0c;常见可以用于webynginx日志、访问日志&#xff0c;消息服务等等&…...

gitlab 通过svn hook 触发

jenkins 起一个item 配置&#xff1a; 我选的自由风格的 源码管理配置 先选subversion 就是svn类型 url 设置project 的路径&#xff0c; 注意是工程&#xff0c;不是svn 顶层 添加一个账户来进行pull 等操作 选择添加的账号 构建触发器&#xff1a; &#xff0c;重要的是要自…...

设计模式详解---单例模式

1. 设计模式详解 单例模式是一种创建对象的设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供全局访问点以获取该实例。 在单例模式中&#xff0c;类负责创建自己的唯一实例&#xff0c;并确保任何其他对象只能访问该实例。这对于需要共享状态或资源的情况非常有…...

毕设之-Hlang后端架构-双系统交互

文章目录 前言交互流程基本流程约定公钥人人中台携带公钥获取私钥私钥生成人人中台携带私钥访问私钥验证&#xff08;博客系统&#xff09; 调试演示总结 前言 前天我们完成了基本的整合&#xff0c;但是还没有整合到我们的业务系统&#xff0c;也就是博客系统。本来昨天要搞一…...

什么同源策略?

同源 同源指的是URL有相同的协议、主机名和端口号。 同源策略 同源策略指的是浏览器提供的安全功能&#xff0c;非同源的RUL之间不能进行资源交互 跨域 两个非同源之间要进行资源交互就是跨域。 浏览器对跨域请求的拦截 浏览器是允许跨域请求的&#xff0c;但是请求返回…...

破译模式:模式识别在计算机视觉中的作用

一、介绍 在当代数字领域&#xff0c;计算机视觉中的模式识别是关键的基石&#xff0c;推动着众多技术进步和应用。本文探讨了计算机视觉中模式识别的本质、方法、应用、挑战和未来趋势。通过使机器能够识别和解释视觉数据中的模式&#xff0c;模式识别不仅推动了计算机视觉领域…...

c语言-全局变量与局部变量

目录 1、&#xff08;作用&#xff09;域的概念 2、全局与局部的相对性 3、生命周期 3、静态变量static 结语&#xff1a; 前言&#xff1a; 在c语言中&#xff0c;全局变量的可见范围是整个工程&#xff0c;而局部变量的可见范围从该变量被定义到该作用域结束&#xff0c…...

【Spring】00 入门指南

文章目录 1.简介2.概念1&#xff09;控制反转&#xff08;IoC&#xff09;2&#xff09;依赖注入&#xff08;DI&#xff09; 3.核心模块1&#xff09;Spring Core2&#xff09;Spring AOP3&#xff09;Spring MVC4&#xff09;Spring Data5&#xff09;Spring Boot 4.编写 Hel…...

BIM 技术:CIM (City Information Modeling) 1-7 级

本心、输入输出、结果 文章目录 BIM 技术&#xff1a;CIM &#xff08;City Information Modeling&#xff09; 1-7 级前言城市信息模型&#xff08;CIM&#xff09;概述城市信息模型分级介绍CIM 1CIM 2CIM 3CIM 4CIM 5CIM 6CIM 7 花有重开日&#xff0c;人无再少年实践是检验真…...

c++ websocket 协议分析与实现

前言 网上有很多第三方库&#xff0c;nopoll,uwebsockets,libwebsockets,都喜欢回调或太复杂&#xff0c;个人只需要在后端用&#xff0c;所以手动写个&#xff1b; 1:环境 ubuntu18 g(支持c11即可) 第三方库:jsoncpp,openssl 2:安装 jsoncpp 读取json 配置文件 用 自动安装 网…...

kali虚拟机无网络

1.查看虚拟机的网卡模式 在虚拟机设置里&#xff0c;一般选择桥接模式&#xff0c;也可以选择NAT模式。 2、你的IP地址是否写死了&#xff08;设置为静态IP&#xff09; vim编辑模式下的命令&#xff1a; 按a或i进入编辑模式&#xff0c;然后按esc键退出编辑模式&#xff0c;s…...

Unity2023.3(Unity6)版本开始将可以发布WebGPU

翻译一段官网上的话&#xff1a; 利用Unity 2023.3(正式发布时应该称为Unity6)中最新的WebGPU图形API集成&#xff0c;尝试最大限度的提升您的网络游戏的真实感。 通过与谷歌的战略合作&#xff0c;Unity实时3D平台的强大的图形功能现在为图形丰富的网络游戏进行微调&#xff0…...

计算机网络期末考试A卷及答案

一、选择题&#xff08;30分&#xff0c;每题1分&#xff09; 世界上第一个网络系统是( C )。 A、ENIAC B、以太网 C、ARPANET D、DECNET 2&#xff0e;在常用的传输介质中&#xff0c;&#xff08; C &#xff09;的带宽最宽、信号传输衰减最小、抗干扰能力最强。 A.双绞线 …...

<蓝桥杯软件赛>零基础备赛20周--第10周--二分

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

C++中string流知识详解和示例

一、概览与类体系 C 提供三种基于内存字符串的流&#xff0c;定义在 <sstream> 中&#xff1a; std::istringstream&#xff1a;输入流&#xff0c;从已有字符串中读取并解析。std::ostringstream&#xff1a;输出流&#xff0c;向内部缓冲区写入内容&#xff0c;最终取…...

MySQL 8.0 OCP 英文题库解析(十三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...