最全 MyBatisPlus 快速入门!

【Mybatis Plus】Mybatis Plus_快速上手 Mybatis-plus简介:Mybatis增强工具,只做增强,不作改变,简化开发,提高效率。所以MP使用crud、本身是无性能损耗的。无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑强大的 CRUD 操作:内置通用 Mapper、通用 Service,提供了大量的通用的CRUD方法,因此可以省去大量手写sql的语句的工作。条件构造器:提供了强大的条件构造器,可以构造各种复杂的查询条件,以应对各种复杂查询。内置分页插件。 阅读详情

一、MP 是什么

MP全称 Mybatis-Plus ,套用官方的解释便是成为 MyBatis 最好的搭档,简称 基友 。它是在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

1. 三大特性

1)润物无声
只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。

2)效率至上
只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间。

3)丰富功能
代码生成、物理分页、性能分析等功能一应俱全。

2. 支持数据库

mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver 、 presto 、 Gauss 、 Firebird
Phoenix 、 clickhouse 、 Sybase ASE 、 OceanBase 、达梦数据库 、虚谷数据库 、人大金仓数据库 、南大通用数据库

3. 框架结构

实话说,以上这些内容只要你打开官网也能看到,那么我们接下来就先来实际操作一番!

二、MP实战

1. 手摸手式项目练习

1)数据库及表准备
sql 语句:

 use test;
 CREATE TABLE `student`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `dept_id` int(0) NULL DEFAULT NULL,
  `name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  `remark` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
 ) ENGINE = InnoDB AUTO_INCREMENT = 7 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Dynamic;
 -- ----------------------------
 -- Records of student
 -- ----------------------------
 INSERT INTO `student` VALUES (1, 1, '小菜', '关注小菜不迷路!');
 INSERT INTO `student` VALUES (2, 2, '小明', '好好学习,天天向上!');

2)pom 依赖

 <dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-test</artifactId>
 </dependency>
 <!--lombok-->
 <dependency>
  <groupId>org.projectlombok</groupId>
  <artifactId>lombok</artifactId>
  <version>1.16.16</version>
 </dependency>
 <!--MP插件-->
 <dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>3.2.0</version>
 </dependency>
 <!--Mysql-->
 <dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.21</version>
 </dependency>
 <!-- 连接池 -->
 <dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid</artifactId>
  <version>1.2.1</version>
 </dependency>
 <!--JUNIT-->
 <dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.13.1</version>
 </dependency>

3)配置文件

 spring:
  datasource:
  url: jdbc:mysql://localhost:3306/test
  username: root
  password: 123456
  driver-class-name: com.mysql.cj.jdbc.Driver

4)实体类

@Data
 @Builder
 @TableName("student")
 public class User {
 ​
  @TableId(type = IdType.AUTO)
  private Integer id;
 ​
  private Integer deptId;
 ​
  private String name;
 ​
  private String remark;
 }

5)Mapper

 public interface UserMapper extends BaseMapper<User> {}

6)测试类

@RunWith(SpringRunner.class)
 @SpringBootTest
 public class MapperTest {
 ​
  @Autowired
  private UserMapper userMapper;
 ​
  @Test
  public void getAll() {
  List<User> users = userMapper.selectList(null);
  users.forEach(System.out::println);
  }
 }
 /** OUTPUT:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
 User(id=2, deptId=1, name=小明, remark=好好学习,天天向上!)
 **/

小菜结:
在以上的结果,我们可以看到已经打印出了数据库中的全部数据(两条)。而并没有看到平时我们需要写的 mapper.xml 文件,只是用到了 usermapper 中的 selectList() 方法,而 UserMapper 继承了 BaseMapper 这个接口,这个接口便是 MybatisPlus 提供给我们的,我们再来看下这个接口给我们提供了哪些方法。

2. CRUD 基操

1)insert

@Test
 public void insert() {
  //这里使用了 lombok 中的建造者模式构建对象
  User user = User.builder().deptId(1).name("小华").remark("小华爱学习").build();
  int insertFlag = userMapper.insert(user);
  log.info("插入影响行数,{} | 小华的ID: {}", insertFlag, user.getId());
 }
 /** OUTPUT:
 插入影响行数,1 | 小华的ID: 8
 **/

可以看到我们不仅插入了数据,而且还获取到了插入数据的 ID ,但是值得注意的是这里的 ID 虽然是自增的,但并非是 MP 默认的 ID生成策略 ,而是我们在实体类中指定的:

在 MP 中支持的主键生成策略有以下几种:

我们既然已经看到了 @TableId 这个注解,那我们再来关注一个常用注解 @TableField

从注解名上我们就可以看出, @TableId 是用来标记主键 ID 的,而 @TableField 是用来标记其他字段的。

可以看得出来这个注解中存在的值还是比较多的,下面介绍几个常用的值:

value
用于解决字段名不一致问题和驼峰命名,比如实体类中属性名为 remark ,但是表中的字段名为 describe ,这个时候就可以使用 @TableField(value=“describe”) 来进行转换。驼峰转换如果在全局中有配置驼峰命名,这个地方可不写。

exist
用于在数据表中不存在的字段,我们可以使用 @TableField(exist = false) 来进行标记

condition
用在预处理 WHERE 实体条件自定义运算规则,比如我配置了 @TableField(condition = SqlCondition.LIKE) ,输出 SQL 为: select 表 where name LIKE CONCAT(’%’,值,’%’) ,其中 SqlCondition 值如下:

update
用在预处理 set 字段自定义注入,比如我配置了 @TableField(update = “%s+1”) ,其中 %s 会填充字段,输出 SQL 为: update 表名 set 字段 = 字段+1 where 条件

select
用于是否查询时约束,如果我们有个字段 remark 是 text 类型的,查询的时候不想查询该字段,那么就可以使用 @TableField(select = false) 来约束查询的时候不查询该字段

2)update
MybatisPlus的更新操作存在两种:

 int updateById(Param("et") T entity);
 ​
 int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

根据 ID 更新

@Test
 public void update() {
  User user = User.builder().id(3).name("小华").remark("小华爱玩游戏").build();
  userMapper.updateById(user);
 }
 /** 更新结果:
 User(id=3, deptId=1, name=小华, remark=小华爱玩游戏)
 **/

根据条件更新

@Test
 public void update() {
  UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
  updateWrapper.eq("name","小华").set("remark","小华爱下棋");
  userMapper.update(null, updateWrapper);
 }
 /** 更新结果:
 User(id=3, deptId=1, name=小华, remark=小华爱下棋)
 **/

我们也可以将要更新的条件放进 user 对象 里面:

 @Test
 public void update() {
  UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
  updateWrapper.eq("name","小华");
  User user = User.builder().remark("小华爱游泳").build();
  userMapper.update(user, updateWrapper);
 }
 /** 更新结果:
 User(id=3, deptId=1, name=小华, remark=小华爱游泳)
 **/

3)delete
在 MybatisPlus 中删除的方式相对于更新多,总共有四种:

int deleteById(Serializable id);
 ​
 int deleteByMap(@Param("cm") Map<String, Object> columnMap);
 ​
 int delete(@Param("ew") Wrapper<T> wrapper);
 ​
 int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

根据 ID 删除

@Test
 public void deleteById() {
  userMapper.deleteById(3);
 }
 /** SQL语句:
 DELETE FROM student WHERE id = 3;
 **/

根据 Map 删除

 @Test
 public void deleteByMap() {
  HashMap<String, Object> columnMap = new HashMap<>();
  columnMap.put("name","小华");
  columnMap.put("remark","小华爱游泳");
  userMapper.deleteByMap(columnMap);
 }
 /** SQL语句:
 DELETE FROM student WHRE name = '小华' AND remark = '小华爱游泳';
 **/

根据 Wrapper 删除

@Test
 public void delete() {
  UpdateWrapper<User> wrapper = new UpdateWrapper<>();
  wrapper.eq("remark","小华爱下棋");
  userMapper.delete(wrapper);
 }
 /** SQL语句:
 DELETE FROM student WHRE remark = '小华爱下棋';
 **/

根据 Wrapper 删除还有另外一种方式,直接将实体类放入 Wrapper 中包装:

 @Test
 public void delete() {
  User user = User.builder().remark("小华爱下棋").build();
  UpdateWrapper<User> wrapper = new UpdateWrapper<>(user);
  userMapper.delete(wrapper);
 }
 /** SQL语句:
 DELETE FROM student WHRE remark = '小华爱下棋';
 **/

根据 ID 批量删除

@Test
 public void deleteBatchIds() {
  List<Integer> idList = new ArrayList<>();
  idList.add(4);
  idList.add(7);
  userMapper.deleteBatchIds(idList);
 }
 /** SQL语句:
 DELETE FROM student WHERE id In (4,7)
 **/

4)select
查询操作在我们开发中是最经常用到的,也是重中之重。 MybatisPlus 中支持查询的方法也比较多,如下:

T selectById(Serializable id);
 ​
 List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
 ​
 List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
 ​
 T selectOne(@Param("ew") Wrapper<T> queryWrapper);
 ​
 Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
 ​
 List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
 ​
 List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
 ​
 List<Object> selectObjs(@aram("ew") Wrapper<T> queryWrapper);
 ​
 IPage<T> selectPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);
 ​
 IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param("ew") Wrapper<T> queryWrapper);

可以看到总共有 10 个方法,我们接下来一个一个测试

查询所有

@Test
 public void selectList() {
  List<User> users = userMapper.selectList(null);
  users.forEach(System.out::println);
 }
 /** 
  OUTPUT:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
 User(id=2, deptId=1, name=小明, remark=好好学习,天天向上!)
  SQL语句:
 SELECT id, dept_id, name, remark FROM student;
 **/

查询数量

 @Test
 public void selectCount() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  queryWrapper.like("name","小");
  System.out.println(userMapper.selectCount(queryWrapper));
 }
 /** 
  OUTPUT:
 2
  SQL语句:
 SELECT COUNT( 1 ) FROM student WHERE (name LIKE '%小%');
 **/

根据 ID 查询

@Test
 public void selectById() {
  User user = userMapper.selectById(1);
  System.out.println(user);
 }
 /** 
  OUTPUT:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
  SQL语句:
 SELECT id, dept_id, name, remark FROM student WHERE ID = 1;
 **/

根据 ID 批量查询

 @Test
 public void selectBatchIds() {
  List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2));
  users.forEach(System.out::println);
 }
 /** 
  OUTPUT:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
 User(id=2, deptId=1, name=小明, remark=好好学习,天天向上!)
  SQL语句:
 SELECT id, dept_id, name, remark FROM student WHERE ID IN (1, 2);
 **/

根据条件查询单条

 @Test
 public void selectOne() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  queryWrapper.eq("name","小菜");
  User user = userMapper.selectOne(queryWrapper);
  System.out.println(user);
 }
 /**
  OUTPUT:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
  SQL语句:
  SELECT id, name, dept_id, remark FROM student WHERE (name = '小菜');
 **/

根据条件查询多条
通过 map 传递参数,不是通过 LIKE 查询,而是通过 = 查询

 @Test
 public void selectByMap() {
  HashMap<String, Object> columnMap = new HashMap<>();
  columnMap.put("name","小");
  List<User> users = userMapper.selectByMap(columnMap);
  users.forEach(System.out::println);
 }
 /**
  OUTPUT:
 null
  SQL语句:
 SELECT id, name, dept_id, remark FROM student WHERE name = '小';
 **/

如果我们没有新建实体类进行结果封装,我们还可以用 Map 来接收结果集:

@Test
 public void selectMaps() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  queryWrapper.like("name","小");
  List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
  maps.forEach(System.out::println);
 }
 /**
  OUTPUT:
 {name=小菜, remark=关注小菜不迷路!, id=1, dept_id=1}
 {name=小明, remark=好好学习,天天向上!, id=2, dept_id=1}
  SQL语句:
 SELECT id, name, dept_id, remark FROM student WHERE (name LIKE '%小%');
 **/

也可以用 Object 对象来接收结果集:

 @Test
 public void selectObjs() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  queryWrapper.like("name", "小");
  List<Object> objects = userMapper.selectObjs(queryWrapper);
 }
 /**
  OUTPUT:
 {name=小菜, remark=关注小菜不迷路!, id=1, dept_id=1}
 {name=小明, remark=好好学习,天天向上!, id=2, dept_id=1}
  SQL语句:
 SELECT id, name, dept_id, remark FROM student WHERE (name LIKE '%小%');
 **/

分页查询

@Test
 public void selectPage() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  queryWrapper.like("name", "小");
  Page<User> page = new Page<>(1, 1);
  IPage<User> userIPage = userMapper.selectPage(page, queryWrapper);
  System.out.println("数据总数:" + userIPage.getTotal());
  System.out.println("总页数:" + userIPage.getPages());
  System.out.println("当前页:" + userIPage.getCurrent());
  System.out.println("页大小:" + userIPage.getSize());
  userIPage.getRecords().forEach(System.out::println);
 }
 /**
  OUTPUT:
 数据总数:2
 总页数:2
 当前页:1
 页大小:1
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
  SQL语句:
  SELECT id, name, dept_id, remark
  FROM student
  WHERE (name LIKE '%小%')
  LIMIT 0,1;
 **/

3. 条件构造器

在 CRUD 的基本操作中,我们想要通过条件查询都是通过 Wrapper 类进行封装的,上面只是简单的用到 eq 和 like 操作。事实上这个类十分强大,我们在下面会详细进行介绍。

1)allEq
全部 eq 或个别 isNull

 allEq(Map<R, V> params)
 allEq(Map<R, V> params, boolean null2IsNull)
 allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
  
 allEq(BiPredicate<R, V> filter, Map<R, V> params)
 allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
 allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)

参数说明:
param: key 为数据库字段名,value 为字段值
nullsIsNull:为 true 则在 map 的 value 为 null 时调用 isNull 方法,为 false 是则忽略 value 为 null 时不调用 isNull 方法

filter:过滤函数,判断是否允许字段传入比对条件中

使用示例:

allEq(Map<R, V> params)
 @Test
 public void testAllEq() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  Map<String,Object> params = new HashMap<>();
  params.put("name","小菜");
  params.put("dept_id",1);
  params.put("remark",null);
  queryWrapper.allEq(params); //会调用 isNull 方法
  userMapper.selectList(queryWrapper);
 }
 /** 
  结果:
 {}
  SQL语句:
  SELECT id,name,dept_id,remark
  FROM student
  WHERE (name = '小菜' AND dept_id = 1 AND remark IS NULL);
  **/
allEq(Map<R, V> params, boolean null2IsNull)
 @Test
 public void testAllEq() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  Map<String,Object> params = new HashMap<>();
  params.put("name","小菜");
  params.put("dept_id",1);
  params.put("remark",null);
  queryWrapper.allEq(params, false); //不会调用 isNull 方法
  userMapper.selectList(queryWrapper);
 }
 /** 
  结果:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!)
  SQL语句:
  SELECT id,name,dept_id,remark
  FROM student
  WHERE (name = '小菜' AND dept_id = 1);
  **/
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
 @Test
 public void testAllEq() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  Map<String,Object> params = new HashMap<>();
  params.put("name","小菜");
  params.put("dept_id",1);
  params.put("remark",null);
  queryWrapper.allEq(false,params,false); //不会带入条件进行查询
  userMapper.selectList(queryWrapper);
 }
 /** 
  结果:
 {name=小菜, remark=关注小菜不迷路!, id=1, dept_id=1}
 {name=小明, remark=好好学习,天天向上!, id=2, dept_id=1}
  SQL语句:
  SELECT id,name,dept_id,remark
  FROM student;
  **/
allEq(BiPredicate<R, V> filter, Map<R, V> params)
 @Test
 public void testAllEq() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  Map<String, Object> params = new HashMap<>();
  params.put("name", "小菜");
  params.put("dept_id", 1);
  params.put("remark", null);
  //只有 key 中含有 “m” 才会用作条件判断
  queryWrapper.allEq((k, v) -> (k.contains("m")), params);
  userMapper.selectList(queryWrapper);
 }
 /** 
  结果:
 0
  SQL语句:
  SELECT id,name,dept_id,remark
  FROM student
  WHERE (name = '小菜' AND remark IS NULL);
  **/

2)比较操作

eq: 相当于 =
ne: 相当于 !=
gt: 相当于 >
ge: 相当于 >=
lt: 相当于 <
le: 相当于 <=
between: 相当于 between ... and ...
notBetween: 相当于 not between ... and ...
in: 相当于 in(.., .., ..)
notIn: 相当于 not in(.., .., ..)

3)模糊查询

like: like("name","小菜") --> name like "%小菜%"
notLike: notLike("name","小菜") --> name not like "%小菜%"
likeLeft: like("name","小菜") --> name like "%小菜"
likeRight: like("name","小菜") --> name like "小菜%"

4)排序

orderBy:
 orderBy(boolean condition, boolean isAsc, R... columns)
orderBy(true, true, "id", "name") --> order by id ASC, name ASC

orderByAsc:
orderByAsc("id","name") --> order by id ASC, name ASC`
orderByDesc:
orderByDesc("id","name) --> order by id Desc, name Desc`

5)逻辑查询
or:拼接:

主动调用 or 表示紧接着下一个方法不是用 and 连接!(不调用 or 则默认为使用 and 连接), eq("id",1).or().eq("name","老王")

嵌套: or(i -> i.eq("name", "李白").ne("status", "活着"))

and:嵌套:

and(i -> i.eq("name", "李白").ne("status", "活着"))

6)select
在MP查询中,默认查询所有的字段,如果有需要也可以通过select方法进行指定字段,如 select(“id”, “name”)

4. 配置讲解

1)基本配置
configLocation
用于指明 MyBatis 配置文件的位置,如果我们有 MyBatis 的配置文件,需将配置文件的路径配置到 configLocation 中

SpringBoot:

 mybatis-plus.config-location = classpath:mybatis-config.xml

SpringMvc:

<bean id="sqlSessionFactory"
 class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
 <property name="configLocation" value="classpath:mybatis-config.xml"/>
 </bean>

mapperLocations
用于指明 Mapper 所对应的 XML 的文件位置,我们在 通用 CRUD 中用到的 Mapper 是直接继承 MP 提供的 BaseMapper ,我们也可以自定义方法,然后在 XML 文件中自定义 SQL ,而这时我们需要告诉 Mapper 所对应 XML 文件的位置

SpringBoot:

 mybatis-plus.mapper-locations = classpath*:mybatis/*.xml

SpringMVC:

 <bean id="sqlSessionFactory"
 class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
 <property name="mapperLocations" value="classpath*:mybatis/*.xml"/>
 </bean>

typeAliasesPackage
用于 MyBatis 别名包扫描路径,通过该属性可以给包中的类注册别名,注册后在 Mapper 对应的 XML 文件中可以直接使用类名,而不用使用全限定的类名

SpringBoot:

mybatis-plus.type-aliases-package = cbuc.life.bean

SpringMVC:

 <bean id="sqlSessionFactory"
 class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
 <property name="typeAliasesPackage"
 value="com.baomidou.mybatisplus.samples.quickstart.entity"/>
 </bean>

2)进阶配置
mapUnderScoreToCamelCase
是否开启自动驼峰命名规则映射,这个配置的默认值是 true ,但是这个属性在 MyBatis 中的默认值是 false ,所以在我们平时的开发中都会将这个配置开启。

#关闭自动驼峰映射,该参数不能和mybatis-plus.config-location同时存在

mybatis-plus.configuration.map-underscore-to-camel-case = false

cacheEnabled
全局地开启或关闭配置文件中的所有映射器已经配置的任何缓存,默认为 true 。

 mybatis-plus.configuration.cache-enabled = false

3)DB 策略配置
idType
全局默认主键类型,设置后,即可省略实体对象中的 @TableId(type = IdType.AUTO) 配置。该配置的默认值为 ID_WORKER

SpringBoot:

 mybatis-plus.global-config.db-config.id-type = auto

SpringMVC:

 <bean id="sqlSessionFactory"
 class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource"/>
      <property name="globalConfig">
          <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
              <property name="dbConfig">
                  <bean         class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                  <property name="idType" value="AUTO"/>
                  </bean>
              </property>
          </bean>
      </property>
 </bean>

tablePrefix
表名前缀,全局配置后可省略 @TableName() 配置。该配置的默认值为 null

SpringBoot:

mybatis-plus.global-config.db-config.table-prefix = yq_

SpringMVC:

<bean id="sqlSessionFactory"
 class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource"/>
      <property name="globalConfig">
          <bean class="com.baomidou.mybatisplus.core.config.GlobalConfig">
              <property name="dbConfig">
                  <bean            class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
                      <property name="idType" value="AUTO"/>
                      <property name="tablePrefix" value="yq_"/>
                  </bean>
              </property>
          </bean>
      </property>
 </bean>

5. 其他扩展

1)自动填充
有时候我们在插入或更新数据的时候,希望有些字段可以自动填充。比如我们平时数据表里面会有个 插入时间 或者 更新时间 这种字段,我们会默认以当前时间填充,在 MP 中我们也可以进行配置。

首先我们需要借助 @TableField(fill = FieldFill.INSERT) 这个注解,在插入时进行填充。

@TableField(fill = FieldFill.INSERT)
private String remark;
其中自动填充的模式如下:

 public enum FieldFill {
  /**
  * 默认不处理
  */
  DEFAULT,
  /**
  * 插入时填充字段
  */
  INSERT,
  /**
  * 更新时填充字段
  */
  UPDATE,
  /**
  * 插入和更新时填充字段
  */
  INSERT_UPDATE
 }

然后我们再编写自定义的填充处理模式:

 @Component
 public class MyMetaObjectHandler implements MetaObjectHandler {
  @Override
  public void insertFill(MetaObject metaObject) {
  Object remark = getFieldValByName("remark", metaObject);
  if (null == remark) {
  setFieldValByName("remark", "好好学习", metaObject);
  }
  }
 ​
  @Override
  public void updateFill(MetaObject metaObject) {
  //自定义更新时填充
  }
 }

测试:

 @Test
 public void testObjectHandler() {
  User user = User.builder().deptId(1).name("小明").build();
  userMapper.insert(user);
 }
 /**
  SQL语句:
 INSERT INTO student ( name, dept_id, remark )
 VALUES ( '小明', 1, '好好学习' );
 **/

可以看到插入时,已经自动将我们填充的字段合并进去。

2)逻辑删除
在开发中,很多时候我们删除数据并不需要真正意义上的物理删除,而是使用逻辑删除,这样子查询的时候需要状态条件,确保被标记的数据不被查询到。 MP 当然也支持这样的功能。

我们需要先为 student 表添加一个字段 status 来声明数据是否被删除, 0 表示被删除,1表示未删除 ,然后也需要在实体类上增加这个属性:

 @TableLogic
 private Integer status;

在 application.yaml 中配置:

 mybatis-plus:
  global-config:
  db-config:
  logic-delete-value: 0
  logic-not-delete-value: 1

测试:

@Test
 public void testLogicDelete() {
  userMapper.deleteById(1);
 }
 /**
  SQL语句:
 UPDATE student SET status=0
 WHERE id=1 AND status=1;
 **/

可以看出这段 SQL 并没有真正删除,而是进行了逻辑删除,只是更新了删除标识

3)通用枚举
如果有性别之类的字段,我们通常会用 0 和 1 来表示,但是查出来我们得进行值转换,这个时候我们就可以使用枚举来解决这个问题:

首先为 student 表添加一个 sex 字段来表示性别, 0 表示女性,1 表示男性 ,然后定义一个枚举类:

 public enum SexEnum implements IEnum<Integer> {
  MAN(1, "男"),
  WOMEN(0, "女");
 ​
  private int code;
 ​
  private String value;
 ​
  SexEnum(int code, String value) {
  this.code = code;
  this.value = value;
  }
 ​
  @Override
  public Integer getValue() {
  return this.code;
  }
  
  //注意要重写此方法,不然会将值转换成 ‘MAN’,而不是 ‘男’
  @Override
  public String toString() {
  return this.value;
  }
 }

然后在实体类中添加对应属性:

 private SexEnum sex;

在 application.yaml 中配置:

 mybatis-plus:
  type-enums-package: cbuc.life.enums

测试:

 @Test
 public void selectOne() {
  QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  queryWrapper.eq("name", "小菜");
  User user = userMapper.selectOne(queryWrapper);
  System.out.println(user);
 }
 /**
  输出结果:
 User(id=1, deptId=1, name=小菜, remark=关注小菜不迷路!, status=1, sex=男)
  SQL语句:
  SELECT id,sex,name,dept_id,remark,status
  FROM student
  WHERE status=1 AND (name = '小菜');
 **/

这篇文章写到这里就告一段落了哦,内容有点长,不过如果能完整看下来,我相信你肯定能够很好的使用 MybatisPlus 啦!

mybatis 和 mybatis-plus 配置文件: 用于配置数据库连接和 MyBatis 运行时所需的各种特性,包含了设置和影响 MyBatis 行为的属性、映射文件的位置。mapper接口和mapper.xml之间需要遵循一定规则,才能成功的让mybatis将mapper接口和mapper.xml绑定起来。创建IUserMapper接口: 用于操作数据库CURD的方法。文件:用于mybatis配置文件读取数据库信息。resources 目录下 创建。resources 目录下 创建。resources 目录下 的。类:用于跟数据库字段做映射。 阅读详情

相关推荐

MybatisPlus详细讲解(适合新手和复习)

本文主要介绍了如何在spingboot中引入并且使用mybatis-plus,适合没有接触过和复习的朋友进行观看

qq_62325622的博客 6993

Mybatis-Plus详解

Mybatis-Plus是一个Mybatis(opens new window)的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发。无侵入:只做增强不做改变,引入它不会对现有工程产生影响。 损耗小:启动即会自动注入基本CURD,性能基本无损耗,直接面向对象操作。 强大的CRUD操作:内置通用Mapper、通用Service,仅仅通过少量配置即可实现单表大部分CRUD操作,更有强大的条件构造器,满足各类使用需求。支持Lambda形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需

互联网底层民工的博客 7万+

【MybatisPlus】快速入门

MybatisPlus快速入门、常用注解及常见配置,五分钟带你学会MybatisPlus!

小谷同学的博客 2528

MyBatis-Plus详解

MyBatis-Plus 是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。官网连接池: 传统开发中,每一次请求都要建立一次数据库连接。每一次数据库连接,使用完后都得断开。频繁的数据库连接操作势必占用很多的系统资源,响应速度必定下降。另外,在高并发时,系统资源被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。解决方案: 为数据库连接建立一个“缓冲池”(连接池)。

火车头的博客 3万+

1、MybatisPlus快速入门

为了简化单表CRUD,MybatisPlus提供了一个基础的BaseMapper接口,其中已经实现了单表的CRUD:因此我们自定义的Mapper只要实现了这个BaseMapper,就无需自己实现单表CRUD了。修改mp-demo中的包下的UserMapper接口,让其继承BaseMapper。

weixin_74397083的博客 1910

MyBatisPlus快速入门(二)MyBatisPlus快速入门体验

相信同学们对MybatisPlus都很好奇,如何不写SQL代码实现对数据的读写,本文手把手教大家如何快速入门MybatisPlus,给你来一次快速入门体验。

Designer 小郑的技术博客 2980

MyBatisPlus--快速入门

从名字中就可以感觉到MybatisPlus与MyBatis之间的渊源,而MyBatis是一个非常流行的持久层框架,主要来做数据库的增删改查,而MyBatisPlus这种命名方式让人不得不往MyBatis的升级版去联想,事实也确实如此,MyBatisPlus就是对MyBatis框架的增强与升级,但MyBatisPlus并不是来替代MyBatis的,MyBatisPlus的官网logo是一只蓝色的小鸟,MyBatis官网的logo是一只红色的小鸟,并且在MyBatisPlus官网下的标语就是。

m0_73856804的博客 2828

【动态规划】背包问题(详细总结,很全)

暴力的解法是指数级别的时间复杂度。进而才需要动态规划的解法来进行优化!背包问题是动态规划(Dynamic Planning) 里的非常重要的一部分,关于几种常见的背包,其关系如下:在解决背包问题的时候,我们通常都是按照如下五部来逐步分析,把这五部都搞透了,算是对动规来理解深入了。二维dp数组01背包,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历一维dp数组01背包,只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。求组合数:外层遍历物品,内层遍历背包。

m0_51370744的博客 4万+

MybatisPlus-快速入门

本文详解MyBatisPlus核心功能,包含SpringBoot整合步骤、入门案例实现、@TableName/@TableId/@TableField等常用注解解析。通过案例,演示增删改查开发流程,5分钟完成基础业务搭建,助你快速掌握高效ORM框架,告别繁琐SQL编写!#Java开发 #框架技巧 #编程干货

Crayon26的博客 1397

ArcGIS Pro中协同区位熵方法在商业选址分析中的应用

本文详细介绍了如何利用ArcGIS Pro中的协同区位熵方法进行科学的商业选址分析。该方法通过量化目标客户与竞争对手在空间上的关联程度,精准识别市场空白区与竞争红海,帮助决策者从“凭感觉”转向“用数据说话”,有效提升选址成功率和投资回报。

weixin_29214559的博客 359

AI图像去噪实战:5种最新深度学习模型在超声图像处理中的效果对比(附代码)

本文对比了2022至2024年间五种前沿深度学习模型在超声图像去噪领域的实战效果,包括FDDL-Net、MG-CNFNet、Dual-TranSpeckle、可控去噪模型及Wave-Mamba。文章深入剖析了各模型的核心创新与架构,并提供了可运行的代码片段,旨在帮助医学影像算法工程师根据不同的性能、速度与临床需求,选择最合适的AI图像去噪解决方案。

1a2s3d4f5g的博客 914

MyBatisPlus快速入门

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

2301_76556912的博客 1195

运行后选择GDB/LLDB出现这样的窗口:launch: program ‘输入程序名称,例如 D:\Desktop\新建文件夹\a.exe‘ does not exist...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值 。

**My Coding Family** 1127

MyBatisPlus-快速入门

为了简化单表CRUD,MybatisPlus提供了一个基础的BaseMapper接口,其中已经实现了单表的CRUD:因此我们自定义的Mapper只要实现了这个BaseMapper,就无需自己实现单表CRUD了。修改mp-demo中的包下的UserMapper接口,让其继承BaseMapper。

m0_45253972的博客 1019

QMK固件OLED显示屏配置教程:从零开始实现个性化键盘显示(实操部分)

本教程详细介绍了如何从零开始配置QMK固件的OLED显示屏,实现个性化键盘显示。首先,文章解释了OLED显示屏的基本概念及其在键盘中的应用,并介绍了I2C和SPI两种通信方式。接着,教程逐步指导用户如何在QMK固件中启用OLED功能,包括在rules.mk中启用OLED、在halconf.h和mcuconf.h中配置I2C功能,以及在config.h中设置I2C和OLED参数。最后,教程展示了如何在keymap.c中编写代码,实现OLED显示内容,并提供了进阶定制功能,如显示当前层信息、按键状态和QMK L

Despacito0o的博客 578

汽车OTA 测试用例

汽车OTA 测试用例

天赐好车的博客 973

MybatisPlus快速入门

通过本文章,让你实现快速入门MybatisPlus,感受到效率的极大提升,体会到MybatisPlus的无侵入和方便快捷的特点,并且引入MybatisPlus不会对现有的工程产生影响,只需要简单配置,就可以快速进行单表的CRUD操作,从而节省大量时间

2301_78179333的博客 1089

量化 insider 爆料! 散户打板必亏?(打板必看!量化资金如何“隔日砸盘”收割散户)

量化开发 insider 爆料💥 散户追的涨停板📉,可能是机构故意做的陷阱!本文从技术视角拆解“涨停陷阱”,帮你看清市场真实逻辑🧠。

XiaoqiangClub的博客 449

MyBatisPlus——1 快速入门

从一个入门案例引出MyBatisPlus,从中可以看出它比传统的MyBatis更方便。然后讲解了MyBatisPlus的常见注解和创建配置。

念头通达 769

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

MybatisPlus之1:快速入门

MybatisPlus是对Mybatis的加强,两者是合作的关系,而不是替代。使用mybatisPlus的步骤1、引入mybatisPlus依赖2、在启动类上,使用@MapperScan扫描整个mapper包3、让每个mapper接口,都继承BaseMapper接口,泛型指定为该mapper接口所操作的实体类类型4、直接调用mapper接口中的方法使用。

casually的博客 1396

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

MybatisPlus入门

MyBatisPlus(简称MP)是基于`MyBatis`框架基础上开发的增强型工具,旨在简化开发、提高效率

weixin_41438423的博客 1万+

MybatisPlus快速入门及常见设置

目前主要的ORM数据库的持久化框架主要有:MyBatis、Hibernate、Spring Data JPA,由于MyBatis的缺点还是较为明显的,所以国内团队就创建了MP来弥补这一缺陷。MybatisPlus (简称 MP)是一个 Mybatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

qq_63218110的博客 3251
上一篇: 五年阿里工作经验,耗时三个月整理出来的面试必问——MySQL笔记
下一篇: python利用第三方类库pandas处理csv excel 导入 导出 mysql 的 demo
prefectjava
博客等级 码龄16年 26粉丝 101原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值