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

SpringBoot整合Mybatis-Plus

文章目录

  • 前言
  • 一、Mybatis-Plus简介
  • 二、框架结构
  • 三、SpringBoot整合Mybatis-Plus
    • 1.依赖
    • 2.配置文件设置
  • 四、前期准备
    • 4.1数据库信息
    • 4.2dao类
    • 4.3pojo类
  • 五、常用注解
    • 5.1 @TableName(value = "")
    • 5.2 @TableId(value="",type = IdType.XXX)
    • 5.3 @TableField("")
    • 5.4@TableLogic(value = "0",delval = "1")
  • 六、方法演示
    • 6.1 新增
    • 6.2 根据ID修改
    • 6.3 根据名字修改
    • 6.4 根据ID查询
    • 6.4 根据ID批量查询
    • 6.5 查询count
    • 6.6 查询List
    • 6.7 lambda表达式按照条件动态查询
    • 6.8 查询字段
    • 6.9 聚合查询
    • 6.10 分组查询
    • 6.11 分页查询
    • 6.12 逻辑删除
  • 总结


前言

本文章将演示SpringBoot整合Mybatis-Plus以及常用常用注解方法


一、Mybatis-Plus简介

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window) 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、框架结构

在这里插入图片描述

通过结构图可以看出MyBatisPlus专门提供了mybatis-plus-boot-starter供SpringBoot使用

三、SpringBoot整合Mybatis-Plus

1.依赖

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

注:此依赖整合了Mybatis和Mybatis-Plus,所以尽量不要再加mybatis的依赖,以免冲突

2.配置文件设置

mybatis:configuration://默认是不允许自动转换驼峰命名,得自己设置为truemap-underscore-to-camel-case: true//起别名type-aliases-package: com.apesource.pojo
mybatis-plus:configuration://默认是允许自动转换驼峰命名map-underscore-to-camel-case: true//开启日志log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

注:mybatis和mybatis-plusd 配置是相互独立且生效的


四、前期准备

4.1数据库信息

在这里插入图片描述

4.2dao类

@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}

dao层的接口使用@Mapper声明可以被自动注入,并且继承Mybatis-Plus提供的BaseMapper类实现通过mapper对象调用CDUR方法

4.3pojo类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {private int stuId;private String stuName;private String stuNick;private String stuHobby;private int stuAge;private int deleted;public Student(String stuName, String stuNick, String stuHobby, int stuAge) {this.stuName = stuName;this.stuNick = stuNick;this.stuHobby = stuHobby;this.stuAge = stuAge;}public Student(String stuName, String stuNick, String stuHobby) {this.stuName = stuName;this.stuNick = stuNick;this.stuHobby = stuHobby;}
}

五、常用注解

5.1 @TableName(value = “”)

作用:将类对应到数据库的某个表上
位置:类
参数:value=表的字段名

5.2 @TableId(value=“”,type = IdType.XXX)

作用:将数据库的主键字段映射到类的属性中
位置:成员变量
参数:value=表的字段名;type=AUTO(0),NONE(1),INPUT(2),ASSIGN_ID(3),ASSIGN_UUID(4);

5.3 @TableField(“”)

作用:将类的属性映射到表的字段
位置:成员变量
参数:value=表的字段名

5.4@TableLogic(value = “0”,delval = “1”)

作用:开启逻辑删除,0表示未删除,1表示以及删除
位置:成员变量
参数:value=正常状态的值,delval=被删除后的值
注:此注解声明的成员变量只有MybatisPlus能识别,如果使用mybatis的方法查询的话,还是能查询到状态是已删除的信息

将以上注解用与Studen类中

@TableName(value = "student")
public class Student implements Serializable {
@TableId(value="stu_id",type = IdType.AUTO)private int stuId;@TableField("stu_name")private String stuName;@TableField("stu_nick")private String stuNick;@TableField("stu_hobby")private String stuHobby;@TableField("stu_age")private int stuAge;@TableField(value = "deleted")@TableLogic(value = "0",delval = "1")private int deleted;
}public Student(String stuName, String stuNick, String stuHobby, int stuAge) {this.stuName = stuName;this.stuNick = stuNick;this.stuHobby = stuHobby;this.stuAge = stuAge;}public Student(String stuName, String stuNick, String stuHobby) {this.stuName = stuName;this.stuNick = stuNick;this.stuHobby = stuHobby;}

六、方法演示

6.1 新增

在测试类中注入
@Autowired
StudentMapper mapper;


@Testpublic void test01() {Student student = new Student("李逵", "黑旋风", "飞斧", 33);int i = mapper.insert(student);System.out.println(i);}

结果如图:
在这里插入图片描述

6.2 根据ID修改

//修改ID@Testpublic void test02() throws Exception {Student student = new Student();student.setStuId(7);student.setStuName("鲁智深");student.setStuAge(38);int i = mapper.updateById(student);System.out.println(i);}

结果如图:
在这里插入图片描述

6.3 根据名字修改

@Testpublic void test03() throws Exception {//1.修改数据Student student = new Student();student.setStuHobby("拔杨柳");//2.创建条件QueryWrapper wrapper = new QueryWrapper();wrapper.eq("stu_name", "鲁智深");int update = mapper.update(student, wrapper);System.out.println(update);}

结果如图:
在这里插入图片描述

6.4 根据ID查询

//根据ID查询@Testpublic void test04() throws Exception {Student student = mapper.selectById(3);System.out.println(student);}

结果如图:
在这里插入图片描述

6.4 根据ID批量查询

//根据ID批量查询@Testpublic void test05() throws Exception {List<Student> students = mapper.selectBatchIds(Arrays.asList(1, 3, 5, 6));students.forEach(System.out::println);}

结果如图:
在这里插入图片描述

6.5 查询count

//查询count@Testpublic void test06() throws Exception {QueryWrapper<Student> wrapper = new QueryWrapper<>();wrapper.eq("stu_hobby", "csgo");Integer integer = mapper.selectCount(wrapper);System.out.println(integer);}

结果如图:
在这里插入图片描述

6.6 查询List

//查询list@Testpublic void test07() throws Exception {QueryWrapper<Student> wrapper = new QueryWrapper<>();
//        wrapper.eq("stu_hobby","csgo").or().eq("stu_age",21);wrapper.eq("stu_hobby", "csgo");wrapper.eq("stu_age", 21);//根据wrapper里的条件查询,返回一个集合List<Student> students = mapper.selectList(wrapper);students.forEach(student -> System.out.println(student));}

结果如图:
在这里插入图片描述

6.7 lambda表达式按照条件动态查询

//模拟动态查询@Testpublic void test09() {//1.前端发送来的数据Integer num1 = null;Integer num2 = 30;//1.查询条件LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();//2.判断
//        if(null != num2){
//            wrapper.lt(Student::getStuAge,num2);
//        }
//        if(null != num1){
//            wrapper.gt(Student::getStuAge,num1);
//        }wrapper.gt(num1 != null, Student::getStuAge, num1);wrapper.lt(num2 != null, Student::getStuAge, num2);//3.查询List<Student> students = mapper.selectList(wrapper);students.forEach(System.out::println);}

结果如图:

在这里插入图片描述

6.8 查询字段

@Testpublic void test10() {//1.条件LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();wrapper.select(Student::getStuName, Student::getStuHobby);//2.查询List<Student> students = mapper.selectList(wrapper);//4.遍历students.forEach(System.out::println);}

结果如图:
在这里插入图片描述

6.9 聚合查询

//投影查询-聚合查询@Testpublic void test11() {//1.查询条件QueryWrapper<Student> wrapper = new QueryWrapper<Student>();//2.判断wrapper.select("count(*) as total,max(stu_age) as maxage,sum(stu_age) as sumage");//3.查询List<Map<String, Object>> list = mapper.selectMaps(wrapper);//4.遍历list.forEach(Map::entrySet);}

结果如图:
在这里插入图片描述

6.10 分组查询

//分组查询@Testpublic void test12() {//1.查询条件QueryWrapper<Student> wrapper = new QueryWrapper<Student>();//2.判断wrapper.select("count(*) as num1,stu_hobby");wrapper.groupBy("stu_hobby");//3.查询List<Map<String, Object>> list = mapper.selectMaps(wrapper);//4.遍历list.forEach(System.out::println);}

结果如图:
在这里插入图片描述

6.11 分页查询

使用分页查询需要在配置类中注入分页类

@Configuration
public class SpringBootConfig {//注入mp拦截器@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){//1.实例化拦截器MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();//2.分页拦截器mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
//        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}
}
/*** mp分页使用* 注意:* 1.page.setCurrent(2);当前页码从1开始* 2.分页需要配置插件* 3.mp坐标版本3.1.1不能使用过高版本*/@Testpublic void test13() throws Exception {//1.定义分页规则IPage<Student> page = new Page<Student>();page.setSize(2);//每页记录数page.setCurrent(2);//当前页码//2.查询条件(可选)IPage<Student> iPage = mapper.selectPage(page, null);List<Student> records = iPage.getRecords();//分页结果records.forEach(System.out::println);System.out.println("每页容量" + iPage.getSize());System.out.println("总记录数:" + iPage.getTotal());System.out.println("总记页数:" + iPage.getPages());}

结果如图:
在这里插入图片描述

6.12 逻辑删除

/*** 物理删除:业务数据从数据库中丢弃,执行的是delete操作* 逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,* 数据保留在数据库中,执行的是update操作* 实现步骤:* 步骤1:修改数据库表添加`deleted`列,比如`0`代表正常,`1`代表删除,可以在添加列的同时设置其默认值为`0`正常。* 步骤2:实体类添加属性以及注解** @TableLogic(value="0",delval="1") private Integer deleted;* value为正常数据的值,delval为删除数据的值*///逻辑删除@Testpublic void test14() {mapper.deleteById(6);}

结果如图:
在这里插入图片描述
在这里插入图片描述

逻辑删除不会真正的将数据从数据库删除,而是对此时使用修改的方式对 @TableLogic声明的属性修改值;但是使用mybatis-plus的查询方法无法将它查到;

总结

由上可知SpringBoot整合Mybatis-Plus后对数据库操作有多方便,因为Mybatis-Plus有强大的条件构造器,满足各类使用需求内置的Mapper,通用的Service,少量配置即可实现单表大部分CRUD操作,支持Lambda形式调用提供了基本的CRUD功能,连SQL语句都不需要编写,自动解析实体关系映射转换为MyBatis内部对象注入容器

相关文章:

SpringBoot整合Mybatis-Plus

文章目录 前言一、Mybatis-Plus简介二、框架结构三、SpringBoot整合Mybatis-Plus1.依赖2.配置文件设置 四、前期准备4.1数据库信息4.2dao类4.3pojo类 五、常用注解5.1 TableName(value "")5.2 TableId(value"",type IdType.XXX)5.3 TableField("&qu…...

在langchain中使用自定义example selector

在langchain中使用自定义example selector 简介 在之前的文章中&#xff0c;我们提到了可以在跟大模型交互的时候&#xff0c;给大模型提供一些具体的例子内容&#xff0c;方便大模型从这些内容中获取想要的答案。这种方便的机制在langchain中叫做FewShotPromptTemplate。 如…...

pytest常用执行参数详解

1. 查看pytest所有可用参数 我们可以通过pytest -h来查看所有可用参数。 从图中可以看出&#xff0c;pytest的参数有很多&#xff0c;下面是归纳一些常用的参数&#xff1a; -s&#xff1a;输出调试信息&#xff0c;包括print打印的信息。 -v&#xff1a;显示更详细的信息。 …...

本地项目如何连接git远程仓库

在本地新建项目后&#xff0c;如何连接git远程仓库呢&#xff1f;步骤如下&#xff1a; 第一步&#xff0c; 首先我们在git上新建仓库&#xff0c;设置模板可勾选Readme文件。&#xff08;readme文件的创建是为了介绍所写代码的一些详细信息,为了之后更好的维护。&#xff09;…...

力扣 494. 目标和

题目来源&#xff1a;https://leetcode.cn/problems/target-sum/description/ C题解&#xff08;来源代码随想录&#xff09;&#xff1a;将该问题转为01背包问题。 假设加法的总和为x&#xff0c;那么减法对应的总和就是sum - x。所以我们要求的是 x - (sum - x) target。x …...

Maven-搭建私有仓库

使用NEXUS REPOSITORY MANAGER 3在Windows上搭建私有仓库。 NEXUS REPOSITORY MANAGER 3 是一个仓库管理系统。 下载NEXUS3 官网上是无法下载的,所以网上搜nexus-3.18.1-01-win64就能搜到,下载即可。 安装NEXUS3 下载nexus-3.18.0-01-win64.zip至相应目录下(路径不要有中文)。 …...

PostgreSql 参数配置

一、访问控制参数配置 https://xiaosonggong.blog.csdn.net/article/details/124264877 二、数据库参数配置 2.1 概述 PostgreSQL 的参数配置参数是在 postgresql.conf 文件中集中管理的&#xff0c;类似于 Oracle 的 pfile 文件&#xff0c;除此之外&#xff0c;PostgreSQL…...

【BMC】OpenBMC开发基础2:修改原有程序

修改原有程序 通常情况下我们会需要修改OpenBMC原有的程序来适配我们的项目&#xff0c;本节将介绍一般的流程。 为此首先我们需要了解devtool这个工具&#xff0c;注意它不是前端开发用的那个devtool&#xff0c;而是由OE&#xff08;或者Yocto&#xff1f;&#xff09;提供…...

2012年数学建模竞赛脑卒中发病环境因素分析及干预日期数据处理代码

因四个表格日期数据处理有些复杂&#xff0c;故作此代码一次性处理四组数据&#xff1a; import datetime import pandas as pddef check(string, df, i, num, error_list):if is_valid(pd.to_datetime(string, errorscoerce, format%Y/%m/%d), error_list, i):df.iloc[i, nu…...

Merge和Rebase的区别

Merge 和 Rebase 是 Git 中常用的两种分支整合方式&#xff0c;它们具有不同的工作原理和效果&#xff1a; Merge&#xff08;合并&#xff09; 合并是将两个或多个分支的提交历史合并为一个新的提交。在合并时&#xff0c;Git 会创建一个新的合并提交&#xff0c;将两个分支…...

[RTKLIB]模糊度固定相关问题(二)

文章目录 一、固定模糊度的前置工作1. 做好固定模糊度的准备2. 建立双差模糊度3. 问题与总结 版权声明&#xff1a;本文为原创文章&#xff0c;版权归 Winston Qu 所有&#xff0c;转载请注明出处。 在上一篇文章中&#xff0c;介绍了RTKLIB中manage_amb_LAMBDA()函数&#xff…...

QtAV for ubuntu16.04

下载ubuntu https://releases.ubuntu.com/16.04/ubuntu-16.04.7-desktop-amd64.iso 下载ffmpeg https://ffmpeg.org/download.html 下载QtAV https://github.com/wang-bin/QtAV/releases 更新 sudo apt update 安装库 sudo apt-get install libglu1-mesa-dev freeglut3-dev…...

MFC 文件读写包括字符串的结构体

试过CString char* 写入的都是地址 struct Param{int ID;int index;char val[128]; };vector<Param>ans; UINT count 17; ans.resize(count); FILE* fp; fopen_s(&fp,_T("my.txt"),_T("rb")); if(count ! fread(&ans[0],sizeof(Param),cou…...

在家构建您的迷你聊天Chat gpt

推荐&#xff1a;使用 NSDT场景编辑器 助你快速搭建可编辑的3D应用场景 什么是指令遵循模型&#xff1f; 语言模型是机器学习模型&#xff0c;可以根据句子的前一个单词预测单词概率。如果我们向模型请求下一个单词&#xff0c;并将其递减地反馈给模型以请求更多单词&#xff…...

pytest自动化测试框架之断言

前言 断言是完整的测试用例中不可或缺的因素&#xff0c;用例只有加入断言&#xff0c;将实际结果与预期结果进行比对&#xff0c;才能判断它的通过与否。 unittest 框架提供了其特有的断言方式&#xff0c;如&#xff1a;assertEqual、assertTrue、assertIn等&#xff0c;py…...

C++模板的用法

目录 模板的概念 函数模板&#xff08;Function Templates&#xff09; 基本用法 函数模板的实例化 匹配原则 类模板&#xff08;Class Templates&#xff09; 模板的概念 C中的模板&#xff08;Templates&#xff09;实际上是一种泛型编程&#xff08;Generic Programm…...

ESP 32 蓝牙虚拟键盘链接笔记本电脑的键值问题

由于打算利用esp32 通过蓝牙链接电脑后实现一些特俗的键盘功能&#xff0c;所以就折腾了一下&#xff0c;折腾最耗费时间的却是键值问题&#xff0c;让一个20多年的老司机重新补充了知识 过程曲折就不说了&#xff0c;直接说结果。 我们通过网络搜索获取的键值和蓝牙模拟键盘传…...

128.【Maven】

Maven仓库 (一)、Maven 简介1.传统项目管理的缺点2.Maven是什么3.Maven的作用 (二)、Maven 的下载与安装1.下载与认识目录2.配置Maven的全局环境 (三)、Maven 的基础概念1.Maven 仓库(1).仓库分类 2. Maven 坐标3.Maven 本地仓库配置(1).改变默认的仓库地址(2).改变远程仓库地址…...

嵌入式虚拟仿真实验教学平台之串口发送数据

嵌入式虚拟仿真实验教学平台课程系列 串口发送数据实验 课程内容 本实验使用 STM32 的串口发送数据。开始仿真后,打开串口监视器&#xff0c;串口监视器会打印出要发送的数据。 课程目标 学习配置使用GPIO功能学习配置使用复用功能学习配置使用UART功能 硬件设计 本课程…...

Android Studio 屏幕适配

Android开发屏幕适配流程 首先studio中没有ScreenMatch这个插件的&#xff0c;下去现在这个插件 点击File->settings->Plugins->(搜索ScreenMatch插件)&#xff0c;点击下载&#xff0c;应用重启Studio即可&#xff0c;如下图 在values下 创建dimens.xml&#xff0c…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

Axios请求超时重发机制

Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式&#xff1a; 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

服务器--宝塔命令

一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行&#xff01; sudo su - 1. CentOS 系统&#xff1a; yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案

目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后&#xff0c;迭代器会失效&#xff0c;因为顺序迭代器在内存中是连续存储的&#xff0c;元素删除后&#xff0c;后续元素会前移。 但一些场景中&#xff0c;我们又需要在执行删除操作…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现指南针功能

指南针功能是许多位置服务应用的基础功能之一。下面我将详细介绍如何在HarmonyOS 5中使用DevEco Studio实现指南针功能。 1. 开发环境准备 确保已安装DevEco Studio 3.1或更高版本确保项目使用的是HarmonyOS 5.0 SDK在项目的module.json5中配置必要的权限 2. 权限配置 在mo…...