9.MyBatis-Plus

1、前期准备
a. 创建数据库
CREATE TABLE USER
(
  id BIGINT(20)NOT NULL COMMENT '主键ID',
  NAME VARCHAR(30)NULL DEFAULT NULL COMMENT '姓名',
  age INT(11)NULL DEFAULT NULL COMMENT '年龄',
  email VARCHAR(50)NULL DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY (id)
);

INSERT INTO user (id, name, age, email)VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
b. 配置项目环境

配置Java编译器:

项目和文件的编码:

c. 添加依赖
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!--mybatis-plus-->
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.3.1</version>
    </dependency>

    <!--mysql依赖-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <!--lombok用来简化实体类-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
d. 配置文件
# 配置MySQL
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/syt_mp?serverTimezone=GMT%2B8
    username: root
    password: 0903he0419
  • 这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为8.0版本的jdbc驱动需要添加这个后缀,否则运行测试用例报告如下错误:java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
  • 这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,否则运行测试用例的时候会有 WARN 信息
e. 启动类
@SpringBootApplication
@MapperScan("com.lemon.demomp.mapper")
public class DemompApplication {

    public static void main(String[] args) {

        SpringApplication.run(DemompApplication.class, args);
    }

}
  • 在启动类添加注解:@MapperScan("com.lemon.demomp.mapper")
f. 添加实体
@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
g. 添加mapper
@Repository
public interface UserMapper extends BaseMapper<User> {

}
  • 为了避免报错,可以在dao 层 的接口上添加 @Repository 注
h. 查看 sql 输出日志
# mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
2、主键策略

插入操作:

//添加
@Test
public void testAdd() {
    User user = new User();
    user.setName("lucy");
    user.setAge(20);
    user.setEmail("1243@qq.com");
    int insert = userMapper.insert(user);
    System.out.println(insert);
}
a. ASSIGN_ID

MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)
private Long id;
b. AUTO 自增策略

需要在创建数据表的时候设置主键自增

实体字段中配置@TableId(type = IdType.AUTO)

@TableId(type = IdType.AUTO)
private Long id;

要想影响所有实体的配置,可以设置全局主键配置

#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto

3、自动填充

注意:update时生成的sql自动是动态sql:UPDATE user SET age=? WHERE id=?

更新操作:

// 修改
@Test
public void testUpdate() {
    User user = new User();
    user.setId(1722996412305653764L);
    user.setName("朱棣");
    int count = userMapper.updateById(user);
    System.out.println(count);
}

需求描述:项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作

a. 修改数据库

在User表中添加datetime类型的新的字段 create_time、update_time

b. 修改实体类

实体上增加字段并添加自动填充注解:

@TableField(fill = FieldFill.INSERT)
private Date createTime;  //create_time

@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time
c. 实现元对象处理接口

src/hander/MyMetaObjectHandler

@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    // mp执行添加操作,这个方法执行
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    // mp 执行修改操作,这个方法执行
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
4、乐观锁

主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新。

乐观锁实现方式:

  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时,set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

乐观锁实现流程:

a. 修改数据库

在user表中新增version字段数据类型为int,给其设定一个默认值(假设为1)

b. 修改实体类

添加 @Version 注解

@Version
private Integer version;
c. 创建配置类

创建包config,创建文件MybatisPlusConfig.java

此时可以删除主类中的 @MapperScan 扫描注解

@Configuration
@MapperScan("com.lemon.demomp.mapper")
public class MpConfig {
    /**
     * 乐观锁插件
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}
d. 测试方法

根据输出结果可以看到,首先经过查询,user的version是1,然后在更改user的name属性,此时version变为2。自此乐观锁已经生效。

@Test
public void testOptimisticLocker() {
    // 1. 根据id进行查询
    User user = userMapper.selectById(1722996412305653768L);
    user.setName("张三");
    int count = userMapper.updateById(user);
    System.out.println(count);
}
5、查询
a. 批量查询

通过多个id进行批量查询

SELECT id,name,age,email,create_time,update_time,version FROM user WHERE id IN ( ? , ? , ? )

==> Parameters: 1(Integer), 2(Integer), 3(Integer)

/*
* 批量查询
* */
@Test
public void testSelectByIds() {
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    System.out.println(users);
}
b. 简单条件查询

SELECT id,name,age,email,create_time,update_time,version FROM user WHERE name = ? AND age = ?

==> Parameters: Jack(String), 20(Integer)

/*
* 简单条件查询
* */
@Test
public void testSelectByMap() {
    Map<String, Object> columnMap = new HashMap<>();
    columnMap.put("name", "Jack");
    columnMap.put("age", 20);
    List<User> users = userMapper.selectByMap(columnMap);
    System.out.println(users);
}
6、分页查询
a. 添加分页插件

在配置类中注册分页插件:src/config/MpConfig

/**
 * 分页插件
 */
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}
b. 测试selectPage

Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?

==> Parameters: 0(Long), 3(Long)

/*
* 测试selectPage分页
* */
@Test
public void testSelectPage() {
    Page<User> page = new Page<>(1, 3);
    Page<User> userPage = userMapper.selectPage(page, null);
    // 返回对象得到分页所有数据
    long pages = userPage.getPages(); //总页数
    long current = userPage.getCurrent(); //当前页
    List<User> records = userPage.getRecords();//查询数据集合
    long total = userPage.getTotal();//总记录数
    boolean hasNext = userPage.hasNext();//是否有下一页
    boolean hasPrevious = userPage.hasPrevious();//是否有上一页

    System.out.println(pages);
    System.out.println(current);
    System.out.println(records);
    System.out.println(total);
    System.out.println(hasNext);
    System.out.println(hasPrevious);

}
c. 测试selectMapsSelect

Preparing: SELECT id,name,age,email,create_time,update_time,version FROM user LIMIT ?,?

==> Parameters: 0(Long), 5(Long)

/*
* 测试selectMapsPage
* */
@Test
public void testSelectMapsPage() {
    //Page不需要泛型
    Page<Map<String, Object>> page = new Page<>(1, 5);
    Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, null);
    List<Map<String, Object>> records = pageParam.getRecords();
    records.forEach(System.out::println);
    System.out.println(pageParam.getCurrent());
    System.out.println(pageParam.getPages());
    System.out.println(pageParam.getSize());
    System.out.println(pageParam.getTotal());
    System.out.println(pageParam.hasNext());
    System.out.println(pageParam.hasPrevious());
}
7、删除
a. 根据id删除记录

Preparing: DELETE FROM user WHERE id=?

==> Parameters: 1(Long)

/*
* 根据id删除记录
* */
@Test
public void testDelById() {
    int isDeleted = userMapper.deleteById(1L);
    System.out.println(isDeleted);
}
b. 批量删除

Preparing: DELETE FROM user WHERE id IN ( ? , ? , ? )

==> Parameters: 2(Integer), 3(Integer), 4(Integer)

/*
* 批量删除
* */
@Test
public void testDelBatchByIds() {
    int isDeleted = userMapper.deleteBatchIds(Arrays.asList(2, 3, 4));
    System.out.println(isDeleted);
}
c. 简单条件删除

Preparing: DELETE FROM user WHERE name = ? AND age = ?

==> Parameters: Billie(String), 24(Integer)

/*
*
* 简单条件删除
* */
@Test
public void testDelByMap() {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "Billie");
    map.put("age", 24);
    int isDeleted = userMapper.deleteByMap(map);
    System.out.println(isDeleted);
}
8、逻辑删除

物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据

逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

逻辑删除的使用场景

  • 可以进行数据恢复
  • 有关联数据,不便删除
a. 修改数据库

添加逻辑删除字段

ALTER TABLE `user` ADD COLUMN deleted BOOLEAN DEFAULT FALSE COMMENT '逻辑删除'
b. 修改实体类

添加deleted 字段,并加上 @TableLogic 注解

@TableLogic
private Integer deleted;
c. 配置文件(可选)

application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无

mybatis-plus:
  global-config:
    db-config:
      id-type: auto
      logic-delete-value: 1
      logic-not-delete-value: 0
d. 测试逻辑删除

Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0

==> Parameters: 6(Long)

测试后发现,数据并没有被删除,deleted字段的值由0变成了1

测试后分析打印的sql语句,是一条update

注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作

/*
* 逻辑删除
* */
@Test
public void testLogicDelete() {
    int isDeleted = userMapper.deleteById(6L);
    System.out.println(isDeleted);
}
e. 测试逻辑删除后的查询

MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0

/*
* 测试逻辑删除后的查询
* */
@Test
public void testLogicDeleteSelect() {
    List<User> users = userMapper.selectList(null);
    users.forEach(System.out::println);
}
9、条件构造器

Wrapper

条件构造抽象类,最顶端父类

AbstractWrapper

用于查询条件封装,生成 sql 的 where 条件

QueryWrapper

查询条件封装

UpdateWrapper

Update 条件封装

AbstractLambdaWrapper

使用Lambda 语法

LambdaQueryWrapper

用于Lambda语法使用的查询Wrapper

LambdaUpdateWrapper

Lambda 更新封装Wrapper

a. ge、gt、le、lt、isNull、isNotNull

UPDATE user SET deleted=1 WHERE deleted=0 AND (name IS NOT NULL AND age >= ? AND email IS NOT NULL)

==> Parameters: 50(Integer)

/*
* ge、gt、le、lt、isNull、isNotNull
* delete
* */
@Test
public void testQuery() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.isNotNull("name")
            .ge("age",50)
            .isNotNull("email");
    int deleted = userMapper.delete(queryWrapper);
    System.out.println("deleted return count= " + deleted);
}
b. eq、ne

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 AND (name = ?)

==> Parameters: 张三(String)

注意:seletOne()返回的是一条实体记录,当出现多条时会报错

/*
* eq、ne
* selectOne
* */
@Test
public void testSelectOne() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name", "张三");
    User user = userMapper.selectOne(queryWrapper);
    System.out.println(user);
}
c. between、notBetween

SELECT COUNT( 1 ) FROM user WHERE deleted=0 AND (age BETWEEN ? AND ?)

==> Parameters: 60(Integer), 80(Integer)

/*
* between,notBetween
* selectCount
* */
@Test
public void testSelectCount() {
    QueryWrapper<User> queryWrapper  = new QueryWrapper<>();
    queryWrapper.between("age", 60, 80);
    Integer count = userMapper.selectCount(queryWrapper);
    System.out.println(count);
}
d. like、notLike、likeLeft、likeRight

SELECT name,age FROM user WHERE deleted=0 AND (name LIKE ? AND email LIKE ?)

==> Parameters: %e%(String), 5%(String)

selectMaps()返回Map集合列表,通常配合select()使用

/*
* like,notLike,likeLeft,likeRight
* selectMaps
* */
@Test
public void testSelectMaps() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("name", "age")
            .like("name", "e")
            .likeRight("email", "5");
    List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}
e. orderBy、orderByDesc、orderByAsc

SELECT id,name,age,email,create_time,update_time,version,deleted FROM user WHERE deleted=0 ORDER BY age DESC,id DESC

/*
* orderBy、orderByDesc、orderByAsc
* selectList
* */
@Test
public void testSelectList() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.orderByDesc("age", "id");
    List<User> users = userMapper.selectList(queryWrapper);
    users.forEach(System.out::println);
}
10、查询方式

setSqlSelect

设置 SELECT 查询字段

where

WHERE 语句,拼接 + WHERE 条件

and

AND 语句,拼接 + AND 字段=值

andNew

AND 语句,拼接 + AND (字段=值)

or

OR 语句,拼接 + OR 字段=值

orNew

OR 语句,拼接 + OR (字段=值)

eq

等于=

allEq

基于 map 内容等于=

ne

不等于<>

gt

大于>

ge

大于等于>=

lt

小于<

le

小于等于<=

like

模糊查询 LIKE

notLike

模糊查询 NOT LIKE

in

IN 查询

notIn

NOT IN 查询

isNull

NULL 值查询

isNotNull

IS NOT NULL

groupBy

分组 GROUP BY

having

HAVING 关键词

orderBy

排序 ORDER BY

orderAsc

ASC 排序 ORDER BY

orderDesc

DESC 排序 ORDER BY

exists

EXISTS 条件语句

notExists

NOT EXISTS 条件语句

between

BETWEEN 条件语句

notBetween

NOT BETWEEN 条件语句

addFilter

自由拼接 SQL

last

拼接在最后,例如:last(“LIMIT 1”)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

亚马逊云科技云存储服务指南

文章作者&#xff1a;Libai 高效的云存储服务对于现代软件开发中的数据管理至关重要。亚马逊云科技云存储服务提供了强大的工具&#xff0c;可以简化工作流程并增强数据管理能力。 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏…

常见的业务分析方法

树状结构分析 由于数据维度的丰富性&#xff0c;不知从哪个维度开始分析&#xff0c;如果每个维度都尝试下探非常耗时。这时可以考虑从总体指标入手&#xff0c;逐层分解总体指标&#xff0c;形成下钻式结构。 分析思路如下&#xff1a; 梳理行业内常见指标&#xff1b;将指…

【Proteus仿真】【51单片机】锂电池管理系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用LCD1602显示模块、DS18B20温度传感器、PCF8691 ADC模块、按键、LED蜂鸣器模块等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示温度…

如何做到百万数据半小时跑批结束

什么是跑批 跑批就是应用程序定时对数据的批量处理。 跑批有以下特性&#xff1a; 大数据量&#xff1a;批量任务一般伴随着大量的数据处理 自动化&#xff1a;要求制定时间或频率自动运行 性能&#xff1a;要求在指定时间内完成批处理任务 健壮性&#xff1a;针对于异常数…

BI 数据可视化平台建设(2)—筛选器组件升级实践

作者&#xff1a;vivo 互联网大数据团队-Wang Lei 本文是vivo互联网大数据团队《BI数据可视化平台建设》系列文章第2篇 -筛选器组件。 本文主要介绍了BI数据可视化平台建设中比较核心的筛选器组件&#xff0c; 涉及组件分类、组件库开发等升级实践经验&#xff0c;通过分享一些…

anaconda中安装pytorch和TensorFlow环境并在不同环境中安装kernel

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Redis最新2023年面试题高级面试题及附答案解析(2)【Redis最新2023年面试题高级面试题及附答案解析-第三十九刊】

文章目录 Redis最新2023年面试题高级面试题及附答案解析(2)01、Redis 集群方案应该怎么做&#xff1f;都有哪些方案&#xff1f;02、Redis 的内存用完了会发生什么&#xff1f;03、怎么测试 Redis 的连通性&#xff1f;04、Redis 集群会有写操作丢失吗&#xff1f;为什么&#…

【java学习—十五】Thread类的有关方法(3)

文章目录 1. 基本方法2. 线程的优先级3. 进阶方法3.1. 举例3.1.1. 线程让步3.1.2. join() 方法3.1.3. sleep()方法3.1.4. stop() 方法3.1.4. isAlive() 方法 1. 基本方法 方法名作用void start()启动线程&#xff0c;并执行对象的 run() 方法run()线程在被调度时执行的操作Str…

T13级专家被毕业?!研发大牛被裁带来的警示丨IDCF

2005年加入腾讯&#xff0c;腾讯第一位Web前端专家&#xff0c;T13职级&#xff0c;今年1月仍是腾讯前端最高专家。 在47岁的时候&#xff0c;拥有这样简历的前端大牛黄希彤被腾讯裁员。 黄希彤夫人在小红书上透露&#xff1a;&#xff08;黄希彤&#xff09;在鹅厂工作了15年…

大语言模型量化方法对比:GPTQ、GGUF、AWQ

在过去的一年里&#xff0c;大型语言模型(llm)有了飞速的发展&#xff0c;在本文中&#xff0c;我们将探讨几种(量化)的方式&#xff0c;除此以外&#xff0c;还会介绍分片及不同的保存和压缩策略。 说明&#xff1a;每次加载LLM示例后&#xff0c;建议清除缓存&#xff0c;以…

ROS 学习应用篇(六)参数的使用与编程

node可能不在一个电脑里但是这些服务的参数信息是共享的&#xff0c;因为话题Topic是异步的所以只有服务Service有实时参数信息可以调用。 接下来将演示服务参数信息的调用与修改。 创建功能包(工作空间src文件夹下) catkin_create_pkg learning_parameter roscpp rospy std…

MySQL中全文索引和普通索引的区别

MySQL中的全文索引&#xff08;Full-Text Index&#xff09;和普通索引&#xff08;比如B-Tree索引&#xff09;是为了提高查询效率而设计的&#xff0c;但它们适用于不同的场景和查询类型。 普通索引&#xff08;如B-Tree索引&#xff09; 适用场景&#xff1a;普通索引适用于…

jsp中使用PDF.js实现pdf文件的预览

本文介绍的是在使用jsp作为模板引擎的spring-mvc项目中&#xff0c;如何利用 PDF.js实现pdf文件的预览。 1、下载 PDF.js Getting Started (mozilla.github.io) 下载解压后其中有两个目录&#xff0c;直接将这两个文件夹放到项目的web资源目录中。此时相当于把PDF.js这个项目也…

3ds max 2024 V-Ray 6 ACES workflow 工作流设置

ACES的流程包括2个设置&#xff1a; 1、环境设置&#xff1b;2、贴图设置&#xff1a; 一、环境设置&#xff1a;3ds max 2024已经内置了OCIO文件&#xff1b;设置一下即可&#xff1b; 二、贴图设置&#xff1a; 所有类型贴图加载有默认和加后缀2种方法&#xff1a; 第一…

使用VC++设计程序使用邻域平均平滑算法、中值滤波算法、K近邻均值滤波器(KNNF)进行滤波

VC实现若干种图像滤波技术 文章目录 VC实现若干种图像滤波技术实验内容邻域平均平滑算法1. 原理2. 实验代码3. 实验现象 中值滤波算法1. 原理2. 实验代码3.实验现象 K近邻均值滤波算法&#xff08;KNNF&#xff09;1. 原理2. 实验代码实验现象 实验内容 实验要求&#xff1a; …

【机器学习】 特征工程:特征预处理,归一化、标准化、处理缺失值

特征预处理采用的是特定的统计方法&#xff08;数学方法&#xff09;将数据转化为算法要求的数字 1. 数值型数据 归一化&#xff0c;将原始数据变换到[0,1]之间 标准化&#xff0c;数据转化到均值为0&#xff0c;方差为1的范围内 缺失值&#xff0c;缺失值处理成均值、中…

PDF处理控件Aspose.PDF功能演示:使用C#查找和替换PDF文件中的文本

使用“查找并替换”选项可以一次性替换文档中的特定文本。这样&#xff0c;您不必手动定位和更新整个文档中每次出现的文本。本文甚至更进一步&#xff0c;介绍了如何在PDF文档中自动查找和替换文本功能。特别是&#xff0c;将学习如何使用C&#xff03;在整个PDF&#xff0c;特…

外汇天眼:失败的投资者经常陷入两个误区!

一、价格与价值的混淆 在金融领域&#xff0c;价格和价值往往被错误视为同义词。然而&#xff0c;审视市场时&#xff0c;我们会逐渐发现一个“安全差”的重要概念&#xff0c;这是由巴菲特的导师本杰明格雷厄姆提出的。 安全差是指股票的内在价值与市场价格之间的差异。内在…

WMS仓储管理系统与TMS系统整合后的优势

随着全球化的加速和供应链网络的日益复杂&#xff0c;仓库和运输成为企业运营中的两个关键环节。为了更高效地管理这两个环节&#xff0c;许多企业开始探索将WMS仓储管理系统和TMS运输管理系统整合的可能性。这种整合不仅可以提升仓库流程的可见性&#xff0c;还有助于改善调度…

1、24 个常见的 Docker 疑难杂症处理技巧(一)

1Docker 迁移存储目录 默认情况系统会将 Docker 容器存放在 /var/lib/docker 目录下 [问题起因] 今天通过监控系统&#xff0c;发现公司其中一台服务器的磁盘快慢&#xff0c;随即上去看了下&#xff0c;发现 /var/lib/docker 这个目录特别大。由上述原因&#xff0c;我们都知…