• Mybatis-Plus复习


    目录

    一.简介

    1.简介

    2.特性

    3.文档参考地址

    二.环境配置

    1.依赖

    2.配置application

    3.实体类

    4.Mapper接口

    三.基本CRUD

    1.BaseMapper

    1.增

    2.删

    3.改

    4.查

    2.IService

    1.测试

    2.注意

    四.常用注解

    1.@TableName("user")

    2.@TableId

    3.@TableField

    4. @TableLogic

    五.条件构造器和常用接口

    1.wrapper(包装)介绍

     2.QueryWrapper和UpdateWrapper

    1.特点

    2.测试

    3.修改 和条件的优先级

    4.查询部分字段

    5. 子查询

    6.动态sql(复杂版)

    7.动态sql简化版

    8.lambda用法

    六.插件

    1.分页插件

    1.配置

    2.使用

    3.根据自定义条件进行分页

    2.乐观锁插件

    1.不用锁

    2.配置乐观锁

    3.用了乐观锁

    4.优化

    七.MybatisX插件

    1.MyBatisX插件用法:

    2.第一个用法生成mapper和service以及实体类模板

     3.第二个用法快捷生成sql

     参考


    一.简介

    1.简介

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

    2.特性

    1.无侵入:只做增强不做改变,引入它不会对现有工程产生影响,损耗小:

    2.启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 强大的 CRUD 操作:

    3.内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,

    4.有强大的条件构造器,满足各类使用需求 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,

    5.支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由 配置,完美解决主键问题 支持

    6.ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强 大的 CRUD 操作

    7. 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,

    8.内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等 同于普通 List 查询 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、 Postgre、SQLServer 等多种数据库

    9.内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出 慢查询

    10.内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防 误操作

    3.文档参考地址

    官方地址: http://mp.baomidou.com
    代码发布地址: Github: https://github.com/baomidou/mybatis-plus Gitee: https://gitee.com/baomidou/mybatis-plus
    文档发布地址: https://baomidou.com/pages/24112f 

    二.环境配置

    1.依赖

    1. <dependency>        
    2. <groupId>com.baomidougroupId>        
    3. <artifactId>mybatis-plus-boot-starterartifactId>        
    4. <version>3.5.1version>    
    5. dependency>

    2.配置application

    1. # 应用名称
    2. spring.application.name=mybatisplus
    3. #默认的数据源
    4. spring.datasource.type=com.zaxxer.hikari.HikariDataSource
    5. spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    6. spring.datasource.url= jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC
    7. spring.datasource.username=root
    8. spring.datasource.password=123456
    9. #显示Sql语句
    10. mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    11. #mybatis-plus.mapper-locations=classpath*:mapper/**/*.xml 默认的配置
    12. #设置实体类所对应表的同一前缀
    13. #mybatis-plus.global-config.db-config.table-prefix=t_
    14. #mybatis-plus.global-config.db-config.table-underline=
    15. #统一设置主键生成策略
    16. #mybatis-plus.global-config.db-config.id-type=auto
    17. #别名
    18. mybatis-plus.type-aliases-package=top.remained.pojo

    3.实体类

    注:

    mybatisPlus 自动配置了驼峰命名 user_name =userName

    mybatisPlus  默认id就是主键

    你主键设置的是递增,如果不在配置文件中主键生成策略,默认仍是雪花算法生成的id

    1. @Data
    2. @AllArgsConstructor
    3. @NoArgsConstructor
    4. public class User {
    5. private Long id;
    6. private String name;
    7. private Integer age;
    8. private String email;
    9. public User(String name, Integer age, String email) {
    10. this.name = name;
    11. this.age = age;
    12. this.email = email;
    13. }
    14. }

    4.Mapper接口

    1. @Mapper
    2. public interface UserMapper extends BaseMapper {
    3. }

    三.基本CRUD

    1.BaseMapper

     Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能

    1. /*
    2. * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
    3. *
    4. * Licensed under the Apache License, Version 2.0 (the "License");
    5. * you may not use this file except in compliance with the License.
    6. * You may obtain a copy of the License at
    7. *
    8. * http://www.apache.org/licenses/LICENSE-2.0
    9. *
    10. * Unless required by applicable law or agreed to in writing, software
    11. * distributed under the License is distributed on an "AS IS" BASIS,
    12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13. * See the License for the specific language governing permissions and
    14. * limitations under the License.
    15. */
    16. package com.baomidou.mybatisplus.core.mapper;
    17. import com.baomidou.mybatisplus.core.conditions.Wrapper;
    18. import com.baomidou.mybatisplus.core.metadata.IPage;
    19. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
    20. import com.baomidou.mybatisplus.core.toolkit.Constants;
    21. import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
    22. import org.apache.ibatis.annotations.Param;
    23. import java.io.Serializable;
    24. import java.util.Collection;
    25. import java.util.List;
    26. import java.util.Map;
    27. /*
    28. :`
    29. .:,
    30. :::,,.
    31. :: `::::::
    32. ::` `,:,` .:`
    33. `:: `::::::::.:` `:';,`
    34. ::::, .:::` `@++++++++:
    35. `` :::` @+++++++++++#
    36. :::, #++++++++++++++`
    37. ,: `::::::;'##++++++++++
    38. .@#@;` ::::::::::::::::::::;
    39. #@####@, :::::::::::::::+#;::.
    40. @@######+@:::::::::::::. #@:;
    41. , @@########':::::::::::: .#''':`
    42. ;##@@@+:##########@::::::::::: @#;.,:.
    43. #@@@######++++#####'::::::::: .##+,:#`
    44. @@@@@#####+++++'#####+::::::::` ,`::@#:`
    45. `@@@@#####++++++'#####+#':::::::::::@.
    46. @@@@######+++++''#######+##';::::;':,`
    47. @@@@#####+++++'''#######++++++++++`
    48. #@@#####++++++''########++++++++'
    49. `#@######+++++''+########+++++++;
    50. `@@#####+++++''##########++++++,
    51. @@######+++++'##########+++++#`
    52. @@@@#####+++++############++++;
    53. ;#@@@@@####++++##############+++,
    54. @@@@@@@@@@@###@###############++'
    55. @#@@@@@@@@@@@@###################+:
    56. `@#@@@@@@@@@@@@@@###################'`
    57. :@#@@@@@@@@@@@@@@@@@##################,
    58. ,@@@@@@@@@@@@@@@@@@@@################;
    59. ,#@@@@@@@@@@@@@@@@@@@##############+`
    60. .#@@@@@@@@@@@@@@@@@@#############@,
    61. @@@@@@@@@@@@@@@@@@@###########@,
    62. :#@@@@@@@@@@@@@@@@##########@,
    63. `##@@@@@@@@@@@@@@@########+,
    64. `+@@@@@@@@@@@@@@@#####@:`
    65. `:@@@@@@@@@@@@@@##@;.
    66. `,'@@@@##@@@+;,`
    67. ``...``
    68. _ _ /_ _ _/_. ____ / _
    69. / / //_//_//_|/ /_\ /_///_/_\ Talk is cheap. Show me the code.
    70. _/ /
    71. */
    72. /**
    73. * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
    74. *

      这个 Mapper 支持 id 泛型

    75. *
    76. * @author hubin
    77. * @since 2016-01-23
    78. */
    79. public interface BaseMapper extends Mapper {
    80. /**
    81. * 插入一条记录
    82. *
    83. * @param entity 实体对象
    84. */
    85. int insert(T entity);
    86. /**
    87. * 根据 ID 删除
    88. *
    89. * @param id 主键ID
    90. */
    91. int deleteById(Serializable id);
    92. /**
    93. * 根据实体(ID)删除
    94. *
    95. * @param entity 实体对象
    96. * @since 3.4.4
    97. */
    98. int deleteById(T entity);
    99. /**
    100. * 根据 columnMap 条件,删除记录
    101. *
    102. * @param columnMap 表字段 map 对象
    103. */
    104. int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
    105. /**
    106. * 根据 entity 条件,删除记录
    107. *
    108. * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
    109. */
    110. int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    111. /**
    112. * 删除(根据ID或实体 批量删除)
    113. *
    114. * @param idList 主键ID列表或实体列表(不能为 null 以及 empty)
    115. */
    116. int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList);
    117. /**
    118. * 根据 ID 修改
    119. *
    120. * @param entity 实体对象
    121. */
    122. int updateById(@Param(Constants.ENTITY) T entity);
    123. /**
    124. * 根据 whereEntity 条件,更新记录
    125. *
    126. * @param entity 实体对象 (set 条件值,可以为 null)
    127. * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
    128. */
    129. int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper);
    130. /**
    131. * 根据 ID 查询
    132. *
    133. * @param id 主键ID
    134. */
    135. T selectById(Serializable id);
    136. /**
    137. * 查询(根据ID 批量查询)
    138. *
    139. * @param idList 主键ID列表(不能为 null 以及 empty)
    140. */
    141. List selectBatchIds(@Param(Constants.COLLECTION) Collection idList);
    142. /**
    143. * 查询(根据 columnMap 条件)
    144. *
    145. * @param columnMap 表字段 map 对象
    146. */
    147. List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
    148. /**
    149. * 根据 entity 条件,查询一条记录
    150. *

      查询一条记录,例如 qw.last("limit 1") 限制取一条记录, 注意:多条数据会报异常

    151. *
    152. * @param queryWrapper 实体对象封装操作类(可以为 null)
    153. */
    154. default T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper) {
    155. List ts = this.selectList(queryWrapper);
    156. if (CollectionUtils.isNotEmpty(ts)) {
    157. if (ts.size() != 1) {
    158. throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records");
    159. }
    160. return ts.get(0);
    161. }
    162. return null;
    163. }
    164. /**
    165. * 根据 Wrapper 条件,判断是否存在记录
    166. *
    167. * @param queryWrapper 实体对象封装操作类
    168. * @return
    169. */
    170. default boolean exists(Wrapper queryWrapper) {
    171. Long count = this.selectCount(queryWrapper);
    172. return null != count && count > 0;
    173. }
    174. /**
    175. * 根据 Wrapper 条件,查询总记录数
    176. *
    177. * @param queryWrapper 实体对象封装操作类(可以为 null)
    178. */
    179. Long selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    180. /**
    181. * 根据 entity 条件,查询全部记录
    182. *
    183. * @param queryWrapper 实体对象封装操作类(可以为 null)
    184. */
    185. List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    186. /**
    187. * 根据 Wrapper 条件,查询全部记录
    188. *
    189. * @param queryWrapper 实体对象封装操作类(可以为 null)
    190. */
    191. List> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    192. /**
    193. * 根据 Wrapper 条件,查询全部记录
    194. *

      注意: 只返回第一个字段的值

    195. *
    196. * @param queryWrapper 实体对象封装操作类(可以为 null)
    197. */
    198. List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper);
    199. /**
    200. * 根据 entity 条件,查询全部记录(并翻页)
    201. *
    202. * @param page 分页查询条件(可以为 RowBounds.DEFAULT)
    203. * @param queryWrapper 实体对象封装操作类(可以为 null)
    204. */
    205. extends IPage> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

    206. /**
    207. * 根据 Wrapper 条件,查询全部记录(并翻页)
    208. *
    209. * @param page 分页查询条件
    210. * @param queryWrapper 实体对象封装操作类
    211. */
    212. extends IPage>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

    213. }
    214. 1.增

      1. //可以对ioc容器自动装配
      2. @SpringBootTest
      3. public class MybatisPlusTest {
      4. @Autowired
      5. private UserMapper userMapper;
      6. @Test
      7. public void insert1(){
      8. // INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
      9. User user = new User("zz", 20, "123.com");
      10. int result = userMapper.insert(user);
      11. System.out.println(result);
      12. // 虽然是自增id,但是使用的是雪花算法的id
      13. // 1564895601187151874id
      14. System.out.println(user.getId()+"id");
      15. }
      16. }

      2.删

      注:这里写1L是因为定义的为long型

      1. @Test
      2. public void del(){
      3. // 通过id删除 DELETE FROM user WHERE id=?
      4. // int i = userMapper.deleteById(20);
      5. 1
      6. // System.out.println(i);
      7. // Map map = new HashMap ();
      8. map里面存放的是条件 DELETE FROM user WHERE age = ?
      9. // map.put("age",20);
      10. 因为年龄为202
      11. // int i1 = userMapper.deleteByMap(map);
      12. // System.out.println(i1);
      13. // DELETE FROM user WHERE id IN ( ? , ? )
      14. List list = Arrays.asList(1L, 2L);
      15. // 批量删除
      16. userMapper.deleteBatchIds(list);
      17. }

      3.改

      1. @Test
      2. public void update(){
      3. // UPDATE user SET name=?, age=?, email=? WHERE id=?
      4. // 必须对象里存放Id 要不然白给 因为没Id 所以不更改
      5. User user =new User("zz",18,"456.com");
      6. userMapper.updateById(user);
      7. User user1 = new User();
      8. user1.setAge(16);
      9. user1.setId(3L);
      10. // UPDATE user SET age=? WHERE id=? 只改对象里有的数据,没有的字段原值不变
      11. userMapper.updateById(user1);
      12. }

      4.查

      1. @Test
      2. public void sel(){
      3. // 通过id查询 SELECT id,name,age,email FROM user WHERE id=?
      4. userMapper.selectById(3L);
      5. // 通过map集合中的条件查询 SELECT id,name,age,email FROM user WHERE age = ?
      6. Map map = new HashMap ();
      7. // 条件为 age=16
      8. map.put("age",16);
      9. //
      10. userMapper.selectByMap(map);
      11. // 批量查询 SELECT id,name,age,email FROM user WHERE id IN ( ? , ? , ? )
      12. List list = Arrays.asList(3L,4L,5L);
      13. userMapper.selectBatchIds(list);
      14. // 通过条件查询一个list集合,若没有条件 则可以设置为null 即查询所有
      15. userMapper.selectList(null);
      16. // 调用自己写的 select * from user where id=?
      17. userMapper.selectMapById(3L);
      18. }

      2.IService

      顶级 Service

      1. /*
      2. * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
      3. *
      4. * Licensed under the Apache License, Version 2.0 (the "License");
      5. * you may not use this file except in compliance with the License.
      6. * You may obtain a copy of the License at
      7. *
      8. * http://www.apache.org/licenses/LICENSE-2.0
      9. *
      10. * Unless required by applicable law or agreed to in writing, software
      11. * distributed under the License is distributed on an "AS IS" BASIS,
      12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13. * See the License for the specific language governing permissions and
      14. * limitations under the License.
      15. */
      16. package com.baomidou.mybatisplus.extension.service;
      17. import com.baomidou.mybatisplus.core.conditions.Wrapper;
      18. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
      19. import com.baomidou.mybatisplus.core.metadata.IPage;
      20. import com.baomidou.mybatisplus.core.toolkit.Assert;
      21. import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
      22. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
      23. import com.baomidou.mybatisplus.extension.conditions.query.ChainQuery;
      24. import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
      25. import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
      26. import com.baomidou.mybatisplus.extension.conditions.update.ChainUpdate;
      27. import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
      28. import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
      29. import com.baomidou.mybatisplus.extension.kotlin.KtQueryChainWrapper;
      30. import com.baomidou.mybatisplus.extension.kotlin.KtUpdateChainWrapper;
      31. import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
      32. import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
      33. import org.springframework.transaction.annotation.Transactional;
      34. import java.io.Serializable;
      35. import java.util.Collection;
      36. import java.util.List;
      37. import java.util.Map;
      38. import java.util.Objects;
      39. import java.util.function.Function;
      40. import java.util.stream.Collectors;
      41. /**
      42. * 顶级 Service
      43. *
      44. * @author hubin
      45. * @since 2018-06-23
      46. */
      47. public interface IService {
      48. /**
      49. * 默认批次提交数量
      50. */
      51. int DEFAULT_BATCH_SIZE = 1000;
      52. /**
      53. * 插入一条记录(选择字段,策略插入)
      54. *
      55. * @param entity 实体对象
      56. */
      57. default boolean save(T entity) {
      58. return SqlHelper.retBool(getBaseMapper().insert(entity));
      59. }
      60. /**
      61. * 插入(批量)
      62. *
      63. * @param entityList 实体对象集合
      64. */
      65. @Transactional(rollbackFor = Exception.class)
      66. default boolean saveBatch(Collection entityList) {
      67. return saveBatch(entityList, DEFAULT_BATCH_SIZE);
      68. }
      69. /**
      70. * 插入(批量)
      71. *
      72. * @param entityList 实体对象集合
      73. * @param batchSize 插入批次数量
      74. */
      75. boolean saveBatch(Collection entityList, int batchSize);
      76. /**
      77. * 批量修改插入
      78. *
      79. * @param entityList 实体对象集合
      80. */
      81. @Transactional(rollbackFor = Exception.class)
      82. default boolean saveOrUpdateBatch(Collection entityList) {
      83. return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
      84. }
      85. /**
      86. * 批量修改插入
      87. *
      88. * @param entityList 实体对象集合
      89. * @param batchSize 每次的数量
      90. */
      91. boolean saveOrUpdateBatch(Collection entityList, int batchSize);
      92. /**
      93. * 根据 ID 删除
      94. *
      95. * @param id 主键ID
      96. */
      97. default boolean removeById(Serializable id) {
      98. return SqlHelper.retBool(getBaseMapper().deleteById(id));
      99. }
      100. /**
      101. * 根据 ID 删除
      102. *
      103. * @param id 主键(类型必须与实体类型字段保持一致)
      104. * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
      105. * @return 删除结果
      106. * @since 3.5.0
      107. */
      108. default boolean removeById(Serializable id, boolean useFill) {
      109. throw new UnsupportedOperationException("不支持的方法!");
      110. }
      111. /**
      112. * 根据实体(ID)删除
      113. *
      114. * @param entity 实体
      115. * @since 3.4.4
      116. */
      117. default boolean removeById(T entity) {
      118. return SqlHelper.retBool(getBaseMapper().deleteById(entity));
      119. }
      120. /**
      121. * 根据 columnMap 条件,删除记录
      122. *
      123. * @param columnMap 表字段 map 对象
      124. */
      125. default boolean removeByMap(Map columnMap) {
      126. Assert.notEmpty(columnMap, "error: columnMap must not be empty");
      127. return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));
      128. }
      129. /**
      130. * 根据 entity 条件,删除记录
      131. *
      132. * @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      133. */
      134. default boolean remove(Wrapper queryWrapper) {
      135. return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));
      136. }
      137. /**
      138. * 删除(根据ID 批量删除)
      139. *
      140. * @param list 主键ID或实体列表
      141. */
      142. default boolean removeByIds(Collection list) {
      143. if (CollectionUtils.isEmpty(list)) {
      144. return false;
      145. }
      146. return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
      147. }
      148. /**
      149. * 批量删除
      150. *
      151. * @param list 主键ID或实体列表
      152. * @param useFill 是否填充(为true的情况,会将入参转换实体进行delete删除)
      153. * @return 删除结果
      154. * @since 3.5.0
      155. */
      156. @Transactional(rollbackFor = Exception.class)
      157. default boolean removeByIds(Collection list, boolean useFill) {
      158. if (CollectionUtils.isEmpty(list)) {
      159. return false;
      160. }
      161. if (useFill) {
      162. return removeBatchByIds(list, true);
      163. }
      164. return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
      165. }
      166. /**
      167. * 批量删除(jdbc批量提交)
      168. *
      169. * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
      170. * @return 删除结果
      171. * @since 3.5.0
      172. */
      173. @Transactional(rollbackFor = Exception.class)
      174. default boolean removeBatchByIds(Collection list) {
      175. return removeBatchByIds(list, DEFAULT_BATCH_SIZE);
      176. }
      177. /**
      178. * 批量删除(jdbc批量提交)
      179. *
      180. * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
      181. * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
      182. * @return 删除结果
      183. * @since 3.5.0
      184. */
      185. @Transactional(rollbackFor = Exception.class)
      186. default boolean removeBatchByIds(Collection list, boolean useFill) {
      187. return removeBatchByIds(list, DEFAULT_BATCH_SIZE, useFill);
      188. }
      189. /**
      190. * 批量删除(jdbc批量提交)
      191. *
      192. * @param list 主键ID或实体列表
      193. * @param batchSize 批次大小
      194. * @return 删除结果
      195. * @since 3.5.0
      196. */
      197. default boolean removeBatchByIds(Collection list, int batchSize) {
      198. throw new UnsupportedOperationException("不支持的方法!");
      199. }
      200. /**
      201. * 批量删除(jdbc批量提交)
      202. *
      203. * @param list 主键ID或实体列表
      204. * @param batchSize 批次大小
      205. * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
      206. * @return 删除结果
      207. * @since 3.5.0
      208. */
      209. default boolean removeBatchByIds(Collection list, int batchSize, boolean useFill) {
      210. throw new UnsupportedOperationException("不支持的方法!");
      211. }
      212. /**
      213. * 根据 ID 选择修改
      214. *
      215. * @param entity 实体对象
      216. */
      217. default boolean updateById(T entity) {
      218. return SqlHelper.retBool(getBaseMapper().updateById(entity));
      219. }
      220. /**
      221. * 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
      222. *
      223. * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
      224. */
      225. default boolean update(Wrapper updateWrapper) {
      226. return update(null, updateWrapper);
      227. }
      228. /**
      229. * 根据 whereEntity 条件,更新记录
      230. *
      231. * @param entity 实体对象
      232. * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
      233. */
      234. default boolean update(T entity, Wrapper updateWrapper) {
      235. return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper));
      236. }
      237. /**
      238. * 根据ID 批量更新
      239. *
      240. * @param entityList 实体对象集合
      241. */
      242. @Transactional(rollbackFor = Exception.class)
      243. default boolean updateBatchById(Collection entityList) {
      244. return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
      245. }
      246. /**
      247. * 根据ID 批量更新
      248. *
      249. * @param entityList 实体对象集合
      250. * @param batchSize 更新批次数量
      251. */
      252. boolean updateBatchById(Collection entityList, int batchSize);
      253. /**
      254. * TableId 注解存在更新记录,否插入一条记录
      255. *
      256. * @param entity 实体对象
      257. */
      258. boolean saveOrUpdate(T entity);
      259. /**
      260. * 根据 ID 查询
      261. *
      262. * @param id 主键ID
      263. */
      264. default T getById(Serializable id) {
      265. return getBaseMapper().selectById(id);
      266. }
      267. /**
      268. * 查询(根据ID 批量查询)
      269. *
      270. * @param idList 主键ID列表
      271. */
      272. default List listByIds(Collection idList) {
      273. return getBaseMapper().selectBatchIds(idList);
      274. }
      275. /**
      276. * 查询(根据 columnMap 条件)
      277. *
      278. * @param columnMap 表字段 map 对象
      279. */
      280. default List listByMap(Map columnMap) {
      281. return getBaseMapper().selectByMap(columnMap);
      282. }
      283. /**
      284. * 根据 Wrapper,查询一条记录
      285. *

        结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")

      286. *
      287. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      288. */
      289. default T getOne(Wrapper queryWrapper) {
      290. return getOne(queryWrapper, true);
      291. }
      292. /**
      293. * 根据 Wrapper,查询一条记录
      294. *
      295. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      296. * @param throwEx 有多个 result 是否抛出异常
      297. */
      298. T getOne(Wrapper queryWrapper, boolean throwEx);
      299. /**
      300. * 根据 Wrapper,查询一条记录
      301. *
      302. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      303. */
      304. Map getMap(Wrapper queryWrapper);
      305. /**
      306. * 根据 Wrapper,查询一条记录
      307. *
      308. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      309. * @param mapper 转换函数
      310. */
      311. V getObj(Wrapper queryWrapper, Functionsuper Object, V> mapper);
      312. /**
      313. * 查询总记录数
      314. *
      315. * @see Wrappers#emptyWrapper()
      316. */
      317. default long count() {
      318. return count(Wrappers.emptyWrapper());
      319. }
      320. /**
      321. * 根据 Wrapper 条件,查询总记录数
      322. *
      323. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      324. */
      325. default long count(Wrapper queryWrapper) {
      326. return SqlHelper.retCount(getBaseMapper().selectCount(queryWrapper));
      327. }
      328. /**
      329. * 查询列表
      330. *
      331. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      332. */
      333. default List list(Wrapper queryWrapper) {
      334. return getBaseMapper().selectList(queryWrapper);
      335. }
      336. /**
      337. * 查询所有
      338. *
      339. * @see Wrappers#emptyWrapper()
      340. */
      341. default List list() {
      342. return list(Wrappers.emptyWrapper());
      343. }
      344. /**
      345. * 翻页查询
      346. *
      347. * @param page 翻页对象
      348. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      349. */
      350. default extends IPage> E page(E page, Wrapper queryWrapper) {
      351. return getBaseMapper().selectPage(page, queryWrapper);
      352. }
      353. /**
      354. * 无条件翻页查询
      355. *
      356. * @param page 翻页对象
      357. * @see Wrappers#emptyWrapper()
      358. */
      359. default extends IPage> E page(E page) {
      360. return page(page, Wrappers.emptyWrapper());
      361. }
      362. /**
      363. * 查询列表
      364. *
      365. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      366. */
      367. default List> listMaps(Wrapper queryWrapper) {
      368. return getBaseMapper().selectMaps(queryWrapper);
      369. }
      370. /**
      371. * 查询所有列表
      372. *
      373. * @see Wrappers#emptyWrapper()
      374. */
      375. default List> listMaps() {
      376. return listMaps(Wrappers.emptyWrapper());
      377. }
      378. /**
      379. * 查询全部记录
      380. */
      381. default List listObjs() {
      382. return listObjs(Function.identity());
      383. }
      384. /**
      385. * 查询全部记录
      386. *
      387. * @param mapper 转换函数
      388. */
      389. default List listObjs(Functionsuper Object, V> mapper) {
      390. return listObjs(Wrappers.emptyWrapper(), mapper);
      391. }
      392. /**
      393. * 根据 Wrapper 条件,查询全部记录
      394. *
      395. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      396. */
      397. default List listObjs(Wrapper queryWrapper) {
      398. return listObjs(queryWrapper, Function.identity());
      399. }
      400. /**
      401. * 根据 Wrapper 条件,查询全部记录
      402. *
      403. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      404. * @param mapper 转换函数
      405. */
      406. default List listObjs(Wrapper queryWrapper, Functionsuper Object, V> mapper) {
      407. return getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
      408. }
      409. /**
      410. * 翻页查询
      411. *
      412. * @param page 翻页对象
      413. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
      414. */
      415. default extends IPage>> E pageMaps(E page, Wrapper queryWrapper) {
      416. return getBaseMapper().selectMapsPage(page, queryWrapper);
      417. }
      418. /**
      419. * 无条件翻页查询
      420. *
      421. * @param page 翻页对象
      422. * @see Wrappers#emptyWrapper()
      423. */
      424. default extends IPage>> E pageMaps(E page) {
      425. return pageMaps(page, Wrappers.emptyWrapper());
      426. }
      427. /**
      428. * 获取对应 entity 的 BaseMapper
      429. *
      430. * @return BaseMapper
      431. */
      432. BaseMapper getBaseMapper();
      433. /**
      434. * 获取 entity 的 class
      435. *
      436. * @return {@link Class}
      437. */
      438. Class getEntityClass();
      439. /**
      440. * 以下的方法使用介绍:
      441. *
      442. * 一. 名称介绍
      443. * 1. 方法名带有 query 的为对数据的查询操作, 方法名带有 update 的为对数据的修改操作
      444. * 2. 方法名带有 lambda 的为内部方法入参 column 支持函数式的
      445. * 二. 支持介绍
      446. *
      447. * 1. 方法名带有 query 的支持以 {@link ChainQuery} 内部的方法名结尾进行数据查询操作
      448. * 2. 方法名带有 update 的支持以 {@link ChainUpdate} 内部的方法名为结尾进行数据修改操作
      449. *
      450. * 三. 使用示例,只用不带 lambda 的方法各展示一个例子,其他类推
      451. * 1. 根据条件获取一条数据: `query().eq("column", value).one()`
      452. * 2. 根据条件删除一条数据: `update().eq("column", value).remove()`
      453. *
      454. */
      455. /**
      456. * 链式查询 普通
      457. *
      458. * @return QueryWrapper 的包装类
      459. */
      460. default QueryChainWrapper query() {
      461. return ChainWrappers.queryChain(getBaseMapper());
      462. }
      463. /**
      464. * 链式查询 lambda 式
      465. *

        注意:不支持 Kotlin

      466. *
      467. * @return LambdaQueryWrapper 的包装类
      468. */
      469. default LambdaQueryChainWrapper lambdaQuery() {
      470. return ChainWrappers.lambdaQueryChain(getBaseMapper());
      471. }
      472. /**
      473. * 链式查询 lambda 式
      474. * kotlin 使用
      475. *
      476. * @return KtQueryWrapper 的包装类
      477. */
      478. default KtQueryChainWrapper ktQuery() {
      479. return ChainWrappers.ktQueryChain(getBaseMapper(), getEntityClass());
      480. }
      481. /**
      482. * 链式查询 lambda 式
      483. * kotlin 使用
      484. *
      485. * @return KtQueryWrapper 的包装类
      486. */
      487. default KtUpdateChainWrapper ktUpdate() {
      488. return ChainWrappers.ktUpdateChain(getBaseMapper(), getEntityClass());
      489. }
      490. /**
      491. * 链式更改 普通
      492. *
      493. * @return UpdateWrapper 的包装类
      494. */
      495. default UpdateChainWrapper update() {
      496. return ChainWrappers.updateChain(getBaseMapper());
      497. }
      498. /**
      499. * 链式更改 lambda 式
      500. *

        注意:不支持 Kotlin

      501. *
      502. * @return LambdaUpdateWrapper 的包装类
      503. */
      504. default LambdaUpdateChainWrapper lambdaUpdate() {
      505. return ChainWrappers.lambdaUpdateChain(getBaseMapper());
      506. }
      507. /**
      508. *

      509. * 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
      510. * 此次修改主要是减少了此项业务代码的代码量(存在性验证之后的saveOrUpdate操作)
      511. *

      512. *
      513. * @param entity 实体对象
      514. */
      515. default boolean saveOrUpdate(T entity, Wrapper updateWrapper) {
      516. return update(entity, updateWrapper) || saveOrUpdate(entity);
      517. }
      518. }
      519. 自己的接口应该定义为

        1. public interface UserService extends IService {
        2. }

        其实现类写成

        1. @Service
        2. public class UserServiceImpl extends ServiceImpl implements UserService {
        3. // 第一个要操作的Mapper接口 第二个要操作的类型
        4. }

        1.测试

        1. @SpringBootTest
        2. public class MybatisPlusServiceTest {
        3. @Autowired
        4. UserService userService;
        5. @Test
        6. public void count(){
        7. // 总记录数版本3.3 SELECT COUNT( 1 ) FROM user
        8. // 版本3.5SELECT COUNT( * ) FROM user
        9. long count = userService.count();
        10. System.out.println(count);
        11. }
        12. @Test
        13. public void insert(){
        14. // mapper里面并没有批量添加 原因:sql语句长
        15. // save是保存 saveOrUpdate既有修改又有添加
        16. // 区分:看实体类中有无id有id就是修改 没id就是添加
        17. List list = new ArrayList<>();
        18. for (int i = 0; i <10 ; i++) {
        19. User user = new User();
        20. user.setAge(16+i);
        21. user.setName("gg"+i);
        22. list.add(user);
        23. }
        24. // INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
        25. // 为什么不是批量添加sql 它是基于BaseMapper实现的 它是基于单个循环添加
        26. boolean b = userService.saveBatch(list);
        27. }
        28. }

        2.注意

        insert变为save

        saveOrUpdate 既有修改又有添加

        区分:看实体类中有无id有id就是修改 没id就是添加

        四.常用注解

        1.@TableName("user")

        实体类所对应的数据库表名 "user"
        1. /*
        2. * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
        3. *
        4. * Licensed under the Apache License, Version 2.0 (the "License");
        5. * you may not use this file except in compliance with the License.
        6. * You may obtain a copy of the License at
        7. *
        8. * http://www.apache.org/licenses/LICENSE-2.0
        9. *
        10. * Unless required by applicable law or agreed to in writing, software
        11. * distributed under the License is distributed on an "AS IS" BASIS,
        12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        13. * See the License for the specific language governing permissions and
        14. * limitations under the License.
        15. */
        16. package com.baomidou.mybatisplus.annotation;
        17. import java.lang.annotation.*;
        18. /**
        19. * 数据库表相关
        20. *
        21. * @author hubin, hanchunlin
        22. * @since 2016-01-23
        23. */
        24. @Documented
        25. @Retention(RetentionPolicy.RUNTIME)
        26. @Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
        27. public @interface TableName {
        28. /**
        29. * 实体对应的表名
        30. */
        31. String value() default "";
        32. /**
        33. * schema
        34. *

        35. * 配置此值将覆盖全局配置的 schema
        36. *
        37. * @since 3.1.1
        38. */
        39. String schema() default "";
        40. /**
        41. * 是否保持使用全局的 tablePrefix 的值
        42. *

          只生效于 既设置了全局的 tablePrefix 也设置了上面 {@link #value()} 的值

        43. *
        44. 如果是 false , 全局的 tablePrefix 不生效
        45. *
        46. * @since 3.1.1
        47. */
        48. boolean keepGlobalPrefix() default false;
        49. /**
        50. * 实体映射结果集,
        51. * 只生效于 mp 自动注入的 method
        52. */
        53. String resultMap() default "";
        54. /**
        55. * 是否自动构建 resultMap 并使用,
        56. * 只生效于 mp 自动注入的 method,
        57. * 如果设置 resultMap 则不会进行 resultMap 的自动构建并注入,
        58. * 只适合个别字段 设置了 typeHandler 或 jdbcType 的情况
        59. *
        60. * @since 3.1.2
        61. */
        62. boolean autoResultMap() default false;
        63. /**
        64. * 需要排除的属性名
        65. *
        66. * @since 3.3.1
        67. */
        68. String[] excludeProperty() default {};
        69. }

        注:如果每个表有前缀可以在配置文件中 统一配置

        #设置实体类所对应表的同一前缀
        #mybatis-plus.global-config.db-config.table-prefix=t_
        

        2.@TableId

        将属性所对应的字段指定为主键 value=数据库中的字段

        不指定type默认id生成是雪花算法 并不是递增

        如果自己主动设置id 主动设置的优先

        1. public @interface TableId {
        2. /**
        3. * 字段名(该值可无)
        4. */
        5. String value() default "";
        6. /**
        7. * 主键类型
        8. * {@link IdType}
        9. */
        10. IdType type() default IdType.NONE;
        11. }

        类型可以为

        1. import lombok.Getter;
        2. /**
        3. * 生成ID类型枚举类
        4. *
        5. * @author hubin
        6. * @since 2015-11-10
        7. */
        8. @Getter
        9. public enum IdType {
        10. /**
        11. * 数据库ID自增
        12. *

          该类型请确保数据库设置了 ID自增 否则无效

        13. */
        14. AUTO(0),
        15. /**
        16. * 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
        17. */
        18. NONE(1),
        19. /**
        20. * 用户输入ID
        21. *

          该类型可以通过自己注册自动填充插件进行填充

        22. */
        23. INPUT(2),
        24. /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
        25. /**
        26. * 分配ID (主键类型为number或string),
        27. * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)
        28. *
        29. * @since 3.3.0
        30. */
        31. ASSIGN_ID(3),
        32. /**
        33. * 分配UUID (主键类型为 string)
        34. * 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))
        35. */
        36. ASSIGN_UUID(4);
        37. private final int key;
        38. IdType(int key) {
        39. this.key = key;
        40. }
        41. }

        雪花算法(粗略)

        不可能只有一张表 储存的数量太多 因此进行表的拆分   
        核心优点 保证拆分时不同表的主键的不重复性 主键有序性(后添加的id>之前添加的ID)

        也可以在全局配置中统一配置

        1. #统一设置主键生成策略
        2. mybatis-plus.global-config.db-config.id-type=auto

        3.@TableField

        注:mybatisplus自动配置了驼峰        

        普通字段对应的数据中的列名
        1. public @interface TableField {
        2. /**
        3. * 数据库字段值
        4. *

        5. * 不需要配置该值的情况:
        6. *
        7. 当 {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 为 true 时,
        8. * (mp下默认是true,mybatis默认是false), 数据库字段值.replace("_","").toUpperCase() == 实体属性名.toUpperCase()
        9. *
        10. 当 {@link com.baomidou.mybatisplus.core.MybatisConfiguration#mapUnderscoreToCamelCase} 为 false 时,
        11. * 数据库字段值.toUpperCase() == 实体属性名.toUpperCase()
        12. */
        13. String value() default "";
        14. /**
        15. * 是否为数据库表字段
        16. *

        17. * 默认 true 存在,false 不存在
        18. */
        19. boolean exist() default true;
        20. /**
        21. * 字段 where 实体查询比较条件
        22. *

        23. * 默认 {@link SqlCondition#EQUAL}
        24. */
        25. String condition() default "";
        26. /**
        27. * 字段 update set 部分注入, 该注解优于 el 注解使用
        28. *

        29. * 例1:@TableField(.. , update="%s+1") 其中 %s 会填充为字段
        30. * 输出 SQL 为:update 表 set 字段=字段+1 where ...
        31. *

        32. * 例2:@TableField(.. , update="now()") 使用数据库时间
        33. * 输出 SQL 为:update 表 set 字段=now() where ...
        34. */
        35. String update() default "";
        36. /**
        37. * 字段验证策略之 insert: 当insert操作时,该字段拼接insert语句时的策略
        38. *

        39. * IGNORED: 直接拼接 insert into table_a(column) values (#{columnProperty});
        40. * NOT_NULL: insert into table_a(column) values (#{columnProperty})
        41. * NOT_EMPTY: insert into table_a(column) values (#{columnProperty})
        42. * NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL
        43. *
        44. * @since 3.1.2
        45. */
        46. FieldStrategy insertStrategy() default FieldStrategy.DEFAULT;
        47. /**
        48. * 字段验证策略之 update: 当更新操作时,该字段拼接set语句时的策略
        49. *

        50. * IGNORED: 直接拼接 update table_a set column=#{columnProperty}, 属性为null/空string都会被set进去
        51. * NOT_NULL: update table_a set column=#{columnProperty}
        52. * NOT_EMPTY: update table_a set column=#{columnProperty}
        53. * NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL
        54. *
        55. * @since 3.1.2
        56. */
        57. FieldStrategy updateStrategy() default FieldStrategy.DEFAULT;
        58. /**
        59. * 字段验证策略之 where: 表示该字段在拼接where条件时的策略
        60. *

        61. * IGNORED: 直接拼接 column=#{columnProperty}
        62. * NOT_NULL: column=#{columnProperty}
        63. * NOT_EMPTY: column=#{columnProperty}
        64. * NOT_EMPTY 如果针对的是非 CharSequence 类型的字段则效果等于 NOT_NULL
        65. *
        66. * @since 3.1.2
        67. */
        68. FieldStrategy whereStrategy() default FieldStrategy.DEFAULT;
        69. /**
        70. * 字段自动填充策略
        71. *

        72. * 在对应模式下将会忽略 insertStrategy 或 updateStrategy 的配置,等于断言该字段必有值
        73. */
        74. FieldFill fill() default FieldFill.DEFAULT;
        75. /**
        76. * 是否进行 select 查询
        77. *

        78. * 大字段可设置为 false 不加入 select 查询范围
        79. */
        80. boolean select() default true;
        81. /**
        82. * 是否保持使用全局的 columnFormat 的值
        83. *

        84. * 只生效于 既设置了全局的 columnFormat 也设置了上面 {@link #value()} 的值
        85. * 如果是 false , 全局的 columnFormat 不生效
        86. *
        87. * @since 3.1.1
        88. */
        89. boolean keepGlobalFormat() default false;
        90. /**
        91. * {@link ResultMapping#property} and {@link ParameterMapping#property}
        92. *
        93. * @since 3.4.4
        94. */
        95. String property() default "";
        96. /**
        97. * JDBC类型 (该默认值不代表会按照该值生效),
        98. * 只生效于 mp 自动注入的 method,
        99. * 建议配合 {@link TableName#autoResultMap()} 一起使用
        100. *

        101. * {@link ResultMapping#jdbcType} and {@link ParameterMapping#jdbcType}
        102. *
        103. * @since 3.1.2
        104. */
        105. JdbcType jdbcType() default JdbcType.UNDEFINED;
        106. /**
        107. * 类型处理器 (该默认值不代表会按照该值生效),
        108. * 只生效于 mp 自动注入的 method,
        109. * 建议配合 {@link TableName#autoResultMap()} 一起使用
        110. *

        111. * {@link ResultMapping#typeHandler} and {@link ParameterMapping#typeHandler}
        112. *
        113. * @since 3.1.2
        114. */
        115. Classextends TypeHandler> typeHandler() default UnknownTypeHandler.class;
        116. /**
        117. * 只在使用了 {@link #typeHandler()} 时判断是否辅助追加 javaType
        118. *

        119. * 一般情况下不推荐使用
        120. * {@link ParameterMapping#javaType}
        121. *
        122. * @since 3.4.0 @2020-07-23
        123. */
        124. boolean javaType() default false;
        125. /**
        126. * 指定小数点后保留的位数,
        127. * 只生效于 mp 自动注入的 method,
        128. * 建议配合 {@link TableName#autoResultMap()} 一起使用
        129. *

        130. * {@link ParameterMapping#numericScale}
        131. *
        132. * @since 3.1.2
        133. */
        134. String numericScale() default "";
        135. }

        4. @TableLogic

        1. public @interface TableLogic {
        2. /**
        3. * 默认逻辑未删除值(该值可无、会自动获取全局配置)
        4. */
        5. String value() default "";
        6. /**
        7. * 默认逻辑删除值(该值可无、会自动获取全局配置)
        8. */
        9. String delval() default "";
        10. }
        逻辑删除的字段 数据库中也要添加    删除变为修改,只不过你查不出来 因为默认查询时会有where id_del=0

        五.条件构造器和常用接口

        1.wrapper(包装)介绍

         

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

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

        QueryWrapper : 查询条件封装

        UpdateWrapper : Update 条件封装

        AbstractLambdaWrapper : 使用Lambda 语法

        LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper

        LambdaUpdateWrapper : Lambda 更新封装Wrappe

         2.QueryWrapper和UpdateWrapper

        1.特点

        1.对象封装操作类

        2.用于组装查询条件

        3.调每一个方法返回值都是用的QueryWrapper(链式结构)

        4.删除和查询都是用QueryWrapper

        5. 默认条件之间拼接and

        6.lambda条件表达式优先执行

        2.测试

        1. @Autowired
        2. UserMapper userMapper;
        3. @Test
        4. public void t1(){
        5. QueryWrapper wrapper = new QueryWrapper<>();
        6. // ge>= le<=
        7. // 第一个是字段名 调每一个方法返回值都是用的QueryWrapper
        8. // 所以是链式结构
        9. // 用户名包含a,年龄在20-30之间,邮箱不为空
        10. QueryWrapper w = wrapper.like("name", "a")
        11. .between("age", 20, 30)
        12. .isNotNull("email");
        13. //SELECT id,name,age,email FROM user
        14. //WHERE (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
        15. // %a%(String), 20(Integer), 30(Integer)
        16. userMapper.selectList(w);
        17. }
        18. @Test
        19. public void t2(){
        20. QueryWrapper wrapper = new QueryWrapper<>();
        21. // 查询用户信息 按照年龄降序排, 年龄相同id升序
        22. // SELECT id,name,age,email FROM user ORDER BY age DESC,id ASC
        23. wrapper.orderByDesc("age")
        24. .orderByAsc("id");
        25. userMapper.selectList(wrapper);
        26. }
        27. // 删除和查询都是用QueryWrapper
        28. @Test
        29. public void del(){
        30. QueryWrapper wrapper = new QueryWrapper<>();
        31. // DELETE FROM user WHERE (age IS NULL AND email IS NULL)
        32. QueryWrapper w = wrapper.isNull("age").isNull("email");
        33. userMapper.delete(w);
        34. }

        3.修改 和条件的优先级

        1. @Test
        2. public void update(){
        3. // 2个参数 第一个为修改为的实体类 第二个是修改条件
        4. QueryWrapper wrapper = new QueryWrapper<>();
        5. // UPDATE user SET name=?, age=?, email=? WHERE (name LIKE ? OR age BETWEEN ? AND ?)
        6. User user = new User("mm",21,"789.com");
        7. wrapper.like("name", "a").or().between("age", 20, 30);
        8. userMapper.update(user,wrapper);
        9. // 1个参数 即第一个设置为null 第二个即是条件也是要修改的内容
        10. // UPDATE user SET name=? WHERE (name LIKE ?)
        11. UpdateWrapper wrapper1 = new UpdateWrapper<>();
        12. wrapper1.set("name","hh").like("name","a");
        13. userMapper.update(null,wrapper1);
        14. }
        15. @Test
        16. public void grade(){
        17. // 默认条件之间拼接and
        18. // 用户名包含a 且(年龄大于20或邮箱为null)
        19. // lambda条件表达式优先执行
        20. UpdateWrapper wrapper = new UpdateWrapper<>();
        21. // UPDATE user SET name=?, age=?, email=?
        22. // WHERE (name LIKE ? AND (age > ? OR email IS NULL))
        23. //
        24. wrapper.like("name","a")
        25. .and(i->i.gt("age",20).or().isNull("email"));
        26. userMapper.update(new User("mm",23,"147.com"),wrapper);
        27. }

        4.查询部分字段

        1. @Test
        2. public void partColumn(){
        3. // 查询部分字段
        4. QueryWrapper wrapper = new QueryWrapper<>();
        5. // SELECT name,age FROM user
        6. wrapper.select("name","age");
        7. userMapper.selectList(wrapper);
        8. }

        5. 子查询

        1. @Test
        2. public void sonSelect(){
        3. // 子查询 id <=100
        4. QueryWrapper wrapper = new QueryWrapper<>();
        5. // 第一个参数 字段名 第二个 参数 条件
        6. // SELECT id,name,age,email FROM user
        7. // WHERE (age IN (select id from user where id<=100))
        8. wrapper.inSql("age","select id from user where id<=100");
        9. userMapper.selectList(wrapper);
        10. }

        6.动态sql(复杂版)

        1. @Test
        2. public void judge(){
        3. // 动态sql
        4. String name="";
        5. Integer ageBegin = 20;
        6. Integer ageEnd = 40;
        7. QueryWrapper wrapper = new QueryWrapper<>();
        8. // SELECT id,name,age,email FROM user WHERE (age >= ? AND age <= ?)
        9. if (StringUtils.isNotBlank(name)){
        10. // isNotBlank 判断是否不为空 不为null 不为空白符
        11. wrapper.like("name",name);
        12. }
        13. if (ageBegin !=null){
        14. wrapper.ge("age",20);
        15. }
        16. if (ageEnd !=null){
        17. wrapper.le("age",ageEnd);
        18. }
        19. userMapper.selectList(wrapper);
        20. }

        7.动态sql简化版

        通过条件判断的condition
        1. @Test
        2. public void simple(){
        3. // 通过条件判断的condition condition 为true执行 反之不执行该条件
        4. String name="";
        5. Integer ageBegin = null;
        6. Integer ageEnd = 40;
        7. QueryWrapper wrapper = new QueryWrapper<>();
        8. // SELECT id,name,age,email FROM user WHERE (age <= ?)
        9. // StringUtils 封装了很多关于String的判断方法
        10. wrapper.like(StringUtils.isNotBlank(name),"name",name)
        11. .ge(ageBegin != null,"age",ageBegin)
        12. .le(ageEnd != null,"age",ageEnd);
        13. userMapper.selectList(wrapper);
        14. }

        8.lambda用法

        1. @Test
        2. public void lambda(){
        3. String name="";
        4. Integer ageBegin = 20;
        5. Integer ageEnd = 40;
        6. LambdaQueryWrapper lambdaQueryWrapper = new LambdaQueryWrapper<>();
        7. // 好处 本来是数据库中的字段 现在通过lambda表达式变为实体类中的属性 防止字段写错
        8. lambdaQueryWrapper.like(StringUtils.isNotBlank(name),User::getName,name)
        9. .ge(ageBegin != null,User::getAge,ageBegin)
        10. .le(ageEnd != null,User::getAge,ageEnd);
        11. }

        六.插件

        1.分页插件

        MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

        注:实现原理就是先查询所有数据然后拦截第一页的数据进行显示

        1.配置

        1. @Configuration
        2. public class MybatisPlusConfig {
        3. // 配置分页插件
        4. @Bean
        5. public MybatisPlusInterceptor mybatisPlusInterceptor(){
        6. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        7. // 数据库之间的分页不相同 DbType.MYSQL
        8. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        9. return interceptor;
        10. }
        11. }

        2.使用

        1. @Autowired
        2. private UserMapper userMapper;
        3. @Autowired
        4. private ProductMapper productMapper;
        5. @Test
        6. public void t1(){
        7. Page page = new Page<>(1,3);
        8. // SELECT id,name,age,email FROM user LIMIT ?
        9. // 只有一个参数,因为是第一页
        10. userMapper.selectPage(page,null);
        11. System.out.println(page);
        12. }

        3.根据自定义条件进行分页

        虽然Sql语句不需要Page,但是如果想用MybatisPlus提供的分页
        ​​​​​​​1.参数中就必须有Page page, 且放在第一个参数
        2.返回值必须是page
        

        1.在Mapper接口里

        1. @Mapper
        2. public interface UserMapper extends BaseMapper {
        3. // 自定义分页插件 通过年龄查出用户信息并分页
        4. // 虽然Sql语句不需要Page,但是如果想用MybatisPlus提供的分页
        5. // 1.参数中就必须有Page page, 且放在第一个参数
        6. // 2.返回值必须是page
        7. Page mySelectPage(@Param("page") Page page,
        8. @Param("age") Integer age);
        9. }

        2.在xml文件中直接sql的筛选条件

        1. mapper
        2. PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        4. <mapper namespace="top.remained.mapper.UserMapper">
        5. <select id="mySelectPage" resultType="User">
        6. select id,name,age,email from user where age > #{age}
        7. select>
        8. mapper>

        3.使用

        1. @Test
        2. public void t2(){
        3. // SELECT COUNT(*) AS total FROM user WHERE age > ?
        4. // select id,name,age,email from user where age > ? LIMIT ?,?
        5. Page page = new Page(2,3);
        6. userMapper.mySelectPage(page,18);
        7. }

        2.乐观锁插件

        乐观锁:

        每次修改之后会核对一下之前的版本号,如果相同修改之后保存,反之进行回滚。

        1.不用锁

        1. @Test
        2. public void te1(){
        3. // 不用锁 出现问题
        4. // 查询价格
        5. Product product = productMapper.selectById(1);
        6. System.out.println(product.getPrice() + ":小李查询");
        7. // 100:小李查询
        8. Product product1 = productMapper.selectById(1);
        9. // 100:小王查询
        10. System.out.println(product1.getPrice() + ":小王查询");
        11. // 小李增加50
        12. product.setPrice(product.getPrice()+50);
        13. // 150
        14. productMapper.updateById(product);
        15. // 小王-30
        16. product1.setPrice(product1.getPrice() -30);
        17. // 70
        18. productMapper.updateById(product1);
        19. // 查询改变后的
        20. System.out.println(productMapper.selectById(1).getPrice()+":最后的");
        21. // 70
        22. }

        2.配置乐观锁

        1.标识乐观锁字段号

        2. 配置乐观锁插件

        1. @Configuration
        2. public class MybatisPlusConfig {
        3. // 配置分页插件
        4. @Bean
        5. public MybatisPlusInterceptor mybatisPlusInterceptor(){
        6. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        7. // 数据库之间的分页不相同
        8. interceptor.addInnerInterceptor
        9. (new PaginationInnerInterceptor(DbType.MYSQL));
        10. // 添加乐观锁机制
        11. interceptor.addInnerInterceptor
        12. (new OptimisticLockerInnerInterceptor());
        13. return interceptor;
        14. }
        15. }

        3.用了乐观锁

        1. @Test
        2. public void te2(){
        3. Product product = productMapper.selectById(1);
        4. System.out.println(product.getPrice() + ":小李查询");
        5. // 100:小李查询
        6. Product product1 = productMapper.selectById(1);
        7. // 100:小王查询
        8. System.out.println(product1.getPrice() + ":小王查询");
        9. // 小李增加50
        10. product.setPrice(product.getPrice()+50);
        11. // 150
        12. productMapper.updateById(product);
        13. // UPDATE t_product SET name=?, price=?,
        14. // version=? WHERE id=? AND version=?
        15. // 小王-30
        16. product1.setPrice(product1.getPrice() -30);
        17. // 70
        18. productMapper.updateById(product1);
        19. // 查询改变后的
        20. System.out.println(productMapper.selectById(1)
        21. .getPrice()+":最后的");
        22. // 150
        23. // 最后version为1
        24. }

        4.优化

        小王之所以不成功 版本号不一致

        解决:如果获取更行后的返回值=0 重新查询 重新更改

        1. @Test
        2. public void te3(){
        3. Product product = productMapper.selectById(1);
        4. Product product1 = productMapper.selectById(1);
        5. product.setPrice(product.getPrice()+50);
        6. productMapper.updateById(product);
        7. product1.setPrice(product1.getPrice() -30);
        8. int i = productMapper.updateById(product1);
        9. if (i == 0) {
        10. product1 = productMapper.selectById(1);
        11. product1.setPrice(product1.getPrice() -30);
        12. productMapper.updateById(product1);
        13. }
        14. System.out.println(productMapper.selectById(1).
        15. getPrice()+":最后的");
        16. // 120 版本号改变2次
        17. }

        七.MybatisX插件

        1.MyBatisX插件用法:

        https://baomidou.com/pages/ba5b24/

        2.第一个用法生成mapper和service以及实体类模板

        环境配置

        idea连接上数据库

        1.选中生成的表 

        2.生成实体类的配置

        3.生成service和mapper的配置

         

        4.

         3.第二个用法快捷生成sql

         

         参考

        https://baomidou.com/pages/ba5b24/

         

      520. 相关阅读:
        233062C++&QTday5
        基于C++的中国行政区域图染色与信息查询 课程论文+任务书+代码
        树状数组的扩展应用
        java云端小区物业智能管理系统计算机毕业设计MyBatis+系统+LW文档+源码+调试部署
        (附源码)计算机毕业设计SSM基于的冠状病毒疫情防控资讯交流推荐网站
        多物种组织载玻片——ProSci 胰腺组织解决方案
        05-jenkins与SonarQube代码审查集成
        pytest学习-pytorch单元测试
        Linux Learnning
        MQ学习之史上最全RabbitMQ(强烈建议收藏)
      521. 原文地址:https://blog.csdn.net/qq_46058550/article/details/126637764