当前位置:   article > 正文

MyBatis-Plus 一、(基础应用)

MyBatis-Plus 一、(基础应用)

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

        mybatis 、mybatis-plus 二者区别:

        MyBatis:

  • 所有SQL语句全部自己写
  • 手动解析实体关系映射转换为MyBatis内部对象注入容器
  • 不支持Lambda形式调用

        Mybatis Plus:

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

        

一、什么是MybatisPlus 

MybatisPlus可以节省大量时间,所有的CRUD代码都可以自动化完成

MyBatis-Plus是一个MyBatis的增强工具,在 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、快速入门

        1、准备数据库:

  1. DROP TABLE IF EXISTS `user`;
  2. CREATE TABLE `user` (
  3. `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  4. `name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
  5. `job` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '工作',
  6. `salary` double NULL DEFAULT NULL COMMENT '工资',
  7. `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  8. `update_time` datetime(0) NULL DEFAULT NULL COMMENT '修改时间',
  9. `deleted` bigint(0) NULL DEFAULT 0 COMMENT '是否删除',
  10. PRIMARY KEY (`id`) USING BTREE
  11. ) ENGINE = InnoDB AUTO_INCREMENT = 191 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
  12. -- ----------------------------
  13. -- Records of user
  14. -- ----------------------------
  15. INSERT INTO `user` VALUES (1, '张三', '随便', 2000, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  16. INSERT INTO `user` VALUES (2, '李四', '程序员', 2800, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  17. INSERT INTO `user` VALUES (3, '王五', '程序员鼓励师', 2700, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  18. INSERT INTO `user` VALUES (4, '王二', '部门总监', 4200, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  19. INSERT INTO `user` VALUES (5, '麻子', '程序员', 3000, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  20. INSERT INTO `user` VALUES (6, '最帅三太子', '程序员', 3500, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  21. INSERT INTO `user` VALUES (7, '苍老师', '程序员', 3700, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  22. INSERT INTO `user` VALUES (8, '波多野结衣', 'CEO', 5000, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);
  23. INSERT INTO `user` VALUES (9, '测试3', '测试工作3', 500, '2024-08-19 17:15:34', '2024-08-19 17:15:34', 0);

        2、创建项目 略

        3、引入依赖:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. <version>2.6.14</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.projectlombok</groupId><!---->
  9. <artifactId>lombok</artifactId>
  10. <optional>true</optional>
  11. <version>1.18.22</version>
  12. </dependency>
  13. <!-- mysql驱动 -->
  14. <dependency>
  15. <groupId>mysql</groupId>
  16. <artifactId>mysql-connector-java</artifactId>
  17. <version>8.0.21</version>
  18. </dependency>
  19. <!-- mybatis plus-->
  20. <dependency>
  21. <groupId>com.baomidou</groupId>
  22. <artifactId>mybatis-plus-boot-starter</artifactId>
  23. <version>3.5.1</version>
  24. </dependency>
  25. </dependencies>

         4、添加配置:

  1. spring:
  2. datasource:
  3. url: jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
  4. driver-class-name: com.mysql.cj.jdbc.Driver
  5. username: root
  6. password: 123456
  7. transaction-isolation: 2 #具体定义可在Transactional->Isolation属性查看
  8. #hikari数据库连接池
  9. hikari:
  10. pool-name: Retail_HikariCP
  11. minimum-idle: 1 #最小空闲连接数量
  12. idle-timeout: 180000 #空闲连接存活最大时间,默认60000010分钟)
  13. maximum-pool-size: 10 #连接池最大连接数,默认是10
  14. auto-commit: true #此属性控制从池返回的连接的默认自动提交行为,默认值:true
  15. max-lifetime: 1800000 #此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认180000030分钟
  16. connection-timeout: 30000 #数据库连接超时时间,默认30秒,即30000

     在spring boot启动类中添加@MapperScan注解,扫描Dao文件夹:   

  1. @SpringBootApplication
  2. @MapperScan("com.test.demo.dao")
  3. public class TESTApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(TESTApplication.class,args);
  6. }
  7. }

        5、编码:

  1. @Getter
  2. @Setter
  3. @ToString(callSuper = true)
  4. @Accessors(chain = true)
  5. @TableName("user")
  6. public class User {
  7. private static final long serialVersionUID = 1L;
  8. @TableId(value = "id", type = IdType.ASSIGN_ID)
  9. private Integer id;
  10. private String name;
  11. private String type;
  12. private String job;
  13. private Double salary;
  14. private LocalDateTime createTime;
  15. private LocalDateTime updateTime;
  16. private Long deleted;
  17. }

        编写Mapper包下的Dao接口 

  1. //再对应的mapper上面实现基本的接口 BaseMapper
  2. @Mapper
  3. public interface UserDao extends BaseMapper<User> {
  4. //所有的CRUD都已经完成
  5. //不需要像以前一样配置一大堆文件:pojo-dao(连接mybatis,配置mapper.xml文件)==>service-controller
  6. }

注意:

要在主启动类上去扫描mapper包下的所有接口:@MapperScan("com.test.demo.dao")

        6、简单使用 

  1. @RestController
  2. @RequestMapping("/user")
  3. public class UserController {
  4. @Autowired
  5. private UserDao userDao;
  6. @GetMapping("/get/{id}")
  7. public User findAll(@PathVariable("id") int id ){
  8. return userDao.selectById(id);
  9. }
  10. }

        

三、增删改查

        上面说我们dao接口继承了BaseMapper之后,基本的crud方法就可以直接使用了,就像举例中的 userDao.selectById(id) 方法一样,我们在 userDao 中并没有写 selectById() 方法,但是继承了BaseMapper之后就可以直接用了。这是因为BaseMapper已经帮我们写好了基本的crud方法,可以简单看一下源码:

  1. public interface BaseMapper<T> extends Mapper<T> {
  2. int insert(T entity);
  3. int deleteById(Serializable id);
  4. int deleteById(T entity);
  5. int deleteByMap(@Param("cm") Map<String, Object> columnMap);
  6. int delete(@Param("ew") Wrapper<T> queryWrapper);
  7. int deleteBatchIds(@Param("coll") Collection<?> idList);
  8. int updateById(@Param("et") T entity);
  9. int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
  10. T selectById(Serializable id);
  11. List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
  12. List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
  13. default T selectOne(@Param("ew") Wrapper<T> queryWrapper) {
  14. List<T> ts = this.selectList(queryWrapper);
  15. if (CollectionUtils.isNotEmpty(ts)) {
  16. if (ts.size() != 1) {
  17. throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records", new Object[0]);
  18. } else {
  19. return ts.get(0);
  20. }
  21. } else {
  22. return null;
  23. }
  24. }
  25. default boolean exists(Wrapper<T> queryWrapper) {
  26. Long count = this.selectCount(queryWrapper);
  27. return null != count && count > 0L;
  28. }
  29. Long selectCount(@Param("ew") Wrapper<T> queryWrapper);
  30. List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
  31. List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
  32. List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
  33. <P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);
  34. <P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T> queryWrapper);
  35. }

        上面的所有方法其实都比较容易理解,insert、delect、update、select开头的方法分别对应着增删改查,page方法代表着分页查询。

        上面的方法涵盖了单表查询的基本方法,所以如果不是复杂sql的,我们直接直接使用现成的方法进行查询。下面对各个方法做一个简单演示。

         以下面几个简单的增删改查方法为例:

  1. int insert(T entity);
  2. int deleteById(Serializable id);
  3. int updateById(@Param("et") T entity);
  4. T selectById(Serializable id);

        这几个方法是最基本的增删改查的方法:

        1、insert 
  1. User user = new User();
  2. user.setName("测试1");
  3. user.setJob("测试工作");
  4. userDao.insert(user);

        说到增加,就得提一下主键的生成策略,在mybatis中主键的生成策略需要配合标签或者注解中的属性来设置。在mybatisplus中主键的生成策略可以通过 @TableId() 注解来设置。这个注解是直接加载主键字段上面的。例如User类中:

  1. @TableId(value = "id", type = IdType.ASSIGN_ID)
  2. private Long id;

        上面这个设置代表的是,id字段对应数据库字段为id,且为主键。 type = IdType.ASSIGN_ID 代表 基于雪花算法的策略生成数据id。我们执行两次保存操作后,会发现数据自动填充了id:
        

         type 也可以设置为 IdType.AUTO ,代表:使用数据库的自增策略,注意:该类型需确保数据库设置了自增id,否则无效。

        加上这个注解之后,不需要再加任何配置,就可以生成主键id,这对于我们操作来说变得非常方便。至于其中的原理会放在后面说。

        还有一个注解顺便提一下:@TableId ,这个注解主要是解决属性所对应字段不一致的情况,比如说当user实体类中的name 属性命名的是 userName ,但是数据库中命名的是 name 这样不一致,查询就无法映射到对应字段,可以加上这个注解代表这两个字段是同一个:

  1. @TableField("name")
  2. private String userName;
         2、delect

        根据主键id 删除对应数据。

userDao.deleteById(1825476600460238849L);
         3、update

        根据主键id修改某条数据。

  1. User user = new User();
  2. user.setUserName("测试2");
  3. user.setJob("测试工作2");
  4. user.setId(1825476862067429378L);
  5. userDao.updateById(user);
        4、select

        根据主键id查询某条数据。

        User user = userDao.selectById(id);

        以上就是最简单的增删改查的用法,对于单表查询其实非常的方便。也就是这个其实帮我们提前写好了很多简单的sql操作,也是常用的sql操作。而且不光是 dao层 ,在service层也封装了很多操作,让我们在service层也可以非常方便进行处理。

        四、service 层增删改查

        如果想要在service层实现增删改查,就需要我们service继承 ServiceImpl 接口,其实也就是继承 Iservice 接口,Iservice 接口中含有方法如下:

  1. public interface IService<T> {
  2. /**
  3. * 默认批次提交数量
  4. */
  5. int DEFAULT_BATCH_SIZE = 1000;
  6. /**
  7. * 插入一条记录(选择字段,策略插入)
  8. *
  9. * @param entity 实体对象
  10. */
  11. default boolean save(T entity) {
  12. return SqlHelper.retBool(getBaseMapper().insert(entity));
  13. }
  14. /**
  15. * 插入(批量)
  16. *
  17. * @param entityList 实体对象集合
  18. */
  19. @Transactional(rollbackFor = Exception.class)
  20. default boolean saveBatch(Collection<T> entityList) {
  21. return saveBatch(entityList, DEFAULT_BATCH_SIZE);
  22. }
  23. /**
  24. * 插入(批量)
  25. *
  26. * @param entityList 实体对象集合
  27. * @param batchSize 插入批次数量
  28. */
  29. boolean saveBatch(Collection<T> entityList, int batchSize);
  30. /**
  31. * 批量修改插入
  32. *
  33. * @param entityList 实体对象集合
  34. */
  35. @Transactional(rollbackFor = Exception.class)
  36. default boolean saveOrUpdateBatch(Collection<T> entityList) {
  37. return saveOrUpdateBatch(entityList, DEFAULT_BATCH_SIZE);
  38. }
  39. /**
  40. * 批量修改插入
  41. *
  42. * @param entityList 实体对象集合
  43. * @param batchSize 每次的数量
  44. */
  45. boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
  46. /**
  47. * 根据 ID 删除
  48. *
  49. * @param id 主键ID
  50. */
  51. default boolean removeById(Serializable id) {
  52. return SqlHelper.retBool(getBaseMapper().deleteById(id));
  53. }
  54. /**
  55. * 根据 ID 删除
  56. *
  57. * @param id 主键(类型必须与实体类型字段保持一致)
  58. * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
  59. * @return 删除结果
  60. * @since 3.5.0
  61. */
  62. default boolean removeById(Serializable id, boolean useFill) {
  63. throw new UnsupportedOperationException("不支持的方法!");
  64. }
  65. /**
  66. * 根据实体(ID)删除
  67. *
  68. * @param entity 实体
  69. * @since 3.4.4
  70. */
  71. default boolean removeById(T entity) {
  72. return SqlHelper.retBool(getBaseMapper().deleteById(entity));
  73. }
  74. /**
  75. * 根据 columnMap 条件,删除记录
  76. *
  77. * @param columnMap 表字段 map 对象
  78. */
  79. default boolean removeByMap(Map<String, Object> columnMap) {
  80. Assert.notEmpty(columnMap, "error: columnMap must not be empty");
  81. return SqlHelper.retBool(getBaseMapper().deleteByMap(columnMap));
  82. }
  83. /**
  84. * 根据 entity 条件,删除记录
  85. *
  86. * @param queryWrapper 实体包装类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  87. */
  88. default boolean remove(Wrapper<T> queryWrapper) {
  89. return SqlHelper.retBool(getBaseMapper().delete(queryWrapper));
  90. }
  91. /**
  92. * 删除(根据ID 批量删除)
  93. *
  94. * @param list 主键ID或实体列表
  95. */
  96. default boolean removeByIds(Collection<?> list) {
  97. if (CollectionUtils.isEmpty(list)) {
  98. return false;
  99. }
  100. return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
  101. }
  102. /**
  103. * 批量删除
  104. *
  105. * @param list 主键ID或实体列表
  106. * @param useFill 是否填充(为true的情况,会将入参转换实体进行delete删除)
  107. * @return 删除结果
  108. * @since 3.5.0
  109. */
  110. @Transactional(rollbackFor = Exception.class)
  111. default boolean removeByIds(Collection<?> list, boolean useFill) {
  112. if (CollectionUtils.isEmpty(list)) {
  113. return false;
  114. }
  115. if (useFill) {
  116. return removeBatchByIds(list, true);
  117. }
  118. return SqlHelper.retBool(getBaseMapper().deleteBatchIds(list));
  119. }
  120. /**
  121. * 批量删除(jdbc批量提交)
  122. *
  123. * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
  124. * @return 删除结果
  125. * @since 3.5.0
  126. */
  127. @Transactional(rollbackFor = Exception.class)
  128. default boolean removeBatchByIds(Collection<?> list) {
  129. return removeBatchByIds(list, DEFAULT_BATCH_SIZE);
  130. }
  131. /**
  132. * 批量删除(jdbc批量提交)
  133. *
  134. * @param list 主键ID或实体列表(主键ID类型必须与实体类型字段保持一致)
  135. * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
  136. * @return 删除结果
  137. * @since 3.5.0
  138. */
  139. @Transactional(rollbackFor = Exception.class)
  140. default boolean removeBatchByIds(Collection<?> list, boolean useFill) {
  141. return removeBatchByIds(list, DEFAULT_BATCH_SIZE, useFill);
  142. }
  143. /**
  144. * 批量删除(jdbc批量提交)
  145. *
  146. * @param list 主键ID或实体列表
  147. * @param batchSize 批次大小
  148. * @return 删除结果
  149. * @since 3.5.0
  150. */
  151. default boolean removeBatchByIds(Collection<?> list, int batchSize) {
  152. throw new UnsupportedOperationException("不支持的方法!");
  153. }
  154. /**
  155. * 批量删除(jdbc批量提交)
  156. *
  157. * @param list 主键ID或实体列表
  158. * @param batchSize 批次大小
  159. * @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
  160. * @return 删除结果
  161. * @since 3.5.0
  162. */
  163. default boolean removeBatchByIds(Collection<?> list, int batchSize, boolean useFill) {
  164. throw new UnsupportedOperationException("不支持的方法!");
  165. }
  166. /**
  167. * 根据 ID 选择修改
  168. *
  169. * @param entity 实体对象
  170. */
  171. default boolean updateById(T entity) {
  172. return SqlHelper.retBool(getBaseMapper().updateById(entity));
  173. }
  174. /**
  175. * 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
  176. *
  177. * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
  178. */
  179. default boolean update(Wrapper<T> updateWrapper) {
  180. return update(null, updateWrapper);
  181. }
  182. /**
  183. * 根据 whereEntity 条件,更新记录
  184. *
  185. * @param entity 实体对象
  186. * @param updateWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper}
  187. */
  188. default boolean update(T entity, Wrapper<T> updateWrapper) {
  189. return SqlHelper.retBool(getBaseMapper().update(entity, updateWrapper));
  190. }
  191. /**
  192. * 根据ID 批量更新
  193. *
  194. * @param entityList 实体对象集合
  195. */
  196. @Transactional(rollbackFor = Exception.class)
  197. default boolean updateBatchById(Collection<T> entityList) {
  198. return updateBatchById(entityList, DEFAULT_BATCH_SIZE);
  199. }
  200. /**
  201. * 根据ID 批量更新
  202. *
  203. * @param entityList 实体对象集合
  204. * @param batchSize 更新批次数量
  205. */
  206. boolean updateBatchById(Collection<T> entityList, int batchSize);
  207. /**
  208. * TableId 注解存在更新记录,否插入一条记录
  209. *
  210. * @param entity 实体对象
  211. */
  212. boolean saveOrUpdate(T entity);
  213. /**
  214. * 根据 ID 查询
  215. *
  216. * @param id 主键ID
  217. */
  218. default T getById(Serializable id) {
  219. return getBaseMapper().selectById(id);
  220. }
  221. /**
  222. * 查询(根据ID 批量查询)
  223. *
  224. * @param idList 主键ID列表
  225. */
  226. default List<T> listByIds(Collection<? extends Serializable> idList) {
  227. return getBaseMapper().selectBatchIds(idList);
  228. }
  229. /**
  230. * 查询(根据 columnMap 条件)
  231. *
  232. * @param columnMap 表字段 map 对象
  233. */
  234. default List<T> listByMap(Map<String, Object> columnMap) {
  235. return getBaseMapper().selectByMap(columnMap);
  236. }
  237. /**
  238. * 根据 Wrapper,查询一条记录 <br/>
  239. * <p>结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")</p>
  240. *
  241. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  242. */
  243. default T getOne(Wrapper<T> queryWrapper) {
  244. return getOne(queryWrapper, true);
  245. }
  246. /**
  247. * 根据 Wrapper,查询一条记录
  248. *
  249. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  250. * @param throwEx 有多个 result 是否抛出异常
  251. */
  252. T getOne(Wrapper<T> queryWrapper, boolean throwEx);
  253. /**
  254. * 根据 Wrapper,查询一条记录
  255. *
  256. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  257. */
  258. Map<String, Object> getMap(Wrapper<T> queryWrapper);
  259. /**
  260. * 根据 Wrapper,查询一条记录
  261. *
  262. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  263. * @param mapper 转换函数
  264. */
  265. <V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
  266. /**
  267. * 查询总记录数
  268. *
  269. * @see Wrappers#emptyWrapper()
  270. */
  271. default long count() {
  272. return count(Wrappers.emptyWrapper());
  273. }
  274. /**
  275. * 根据 Wrapper 条件,查询总记录数
  276. *
  277. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  278. */
  279. default long count(Wrapper<T> queryWrapper) {
  280. return SqlHelper.retCount(getBaseMapper().selectCount(queryWrapper));
  281. }
  282. /**
  283. * 查询列表
  284. *
  285. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  286. */
  287. default List<T> list(Wrapper<T> queryWrapper) {
  288. return getBaseMapper().selectList(queryWrapper);
  289. }
  290. /**
  291. * 查询所有
  292. *
  293. * @see Wrappers#emptyWrapper()
  294. */
  295. default List<T> list() {
  296. return list(Wrappers.emptyWrapper());
  297. }
  298. /**
  299. * 翻页查询
  300. *
  301. * @param page 翻页对象
  302. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  303. */
  304. default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper) {
  305. return getBaseMapper().selectPage(page, queryWrapper);
  306. }
  307. /**
  308. * 无条件翻页查询
  309. *
  310. * @param page 翻页对象
  311. * @see Wrappers#emptyWrapper()
  312. */
  313. default <E extends IPage<T>> E page(E page) {
  314. return page(page, Wrappers.emptyWrapper());
  315. }
  316. /**
  317. * 查询列表
  318. *
  319. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  320. */
  321. default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
  322. return getBaseMapper().selectMaps(queryWrapper);
  323. }
  324. /**
  325. * 查询所有列表
  326. *
  327. * @see Wrappers#emptyWrapper()
  328. */
  329. default List<Map<String, Object>> listMaps() {
  330. return listMaps(Wrappers.emptyWrapper());
  331. }
  332. /**
  333. * 查询全部记录
  334. */
  335. default List<Object> listObjs() {
  336. return listObjs(Function.identity());
  337. }
  338. /**
  339. * 查询全部记录
  340. *
  341. * @param mapper 转换函数
  342. */
  343. default <V> List<V> listObjs(Function<? super Object, V> mapper) {
  344. return listObjs(Wrappers.emptyWrapper(), mapper);
  345. }
  346. /**
  347. * 根据 Wrapper 条件,查询全部记录
  348. *
  349. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  350. */
  351. default List<Object> listObjs(Wrapper<T> queryWrapper) {
  352. return listObjs(queryWrapper, Function.identity());
  353. }
  354. /**
  355. * 根据 Wrapper 条件,查询全部记录
  356. *
  357. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  358. * @param mapper 转换函数
  359. */
  360. default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
  361. return getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
  362. }
  363. /**
  364. * 翻页查询
  365. *
  366. * @param page 翻页对象
  367. * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
  368. */
  369. default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper) {
  370. return getBaseMapper().selectMapsPage(page, queryWrapper);
  371. }
  372. /**
  373. * 无条件翻页查询
  374. *
  375. * @param page 翻页对象
  376. * @see Wrappers#emptyWrapper()
  377. */
  378. default <E extends IPage<Map<String, Object>>> E pageMaps(E page) {
  379. return pageMaps(page, Wrappers.emptyWrapper());
  380. }
  381. /**
  382. * 获取对应 entity 的 BaseMapper
  383. *
  384. * @return BaseMapper
  385. */
  386. BaseMapper<T> getBaseMapper();
  387. /**
  388. * 获取 entity 的 class
  389. *
  390. * @return {@link Class<T>}
  391. */
  392. Class<T> getEntityClass();
  393. /**
  394. * 以下的方法使用介绍:
  395. *
  396. * 一. 名称介绍
  397. * 1. 方法名带有 query 的为对数据的查询操作, 方法名带有 update 的为对数据的修改操作
  398. * 2. 方法名带有 lambda 的为内部方法入参 column 支持函数式的
  399. * 二. 支持介绍
  400. *
  401. * 1. 方法名带有 query 的支持以 {@link ChainQuery} 内部的方法名结尾进行数据查询操作
  402. * 2. 方法名带有 update 的支持以 {@link ChainUpdate} 内部的方法名为结尾进行数据修改操作
  403. *
  404. * 三. 使用示例,只用不带 lambda 的方法各展示一个例子,其他类推
  405. * 1. 根据条件获取一条数据: `query().eq("column", value).one()`
  406. * 2. 根据条件删除一条数据: `update().eq("column", value).remove()`
  407. *
  408. */
  409. /**
  410. * 链式查询 普通
  411. *
  412. * @return QueryWrapper 的包装类
  413. */
  414. default QueryChainWrapper<T> query() {
  415. return ChainWrappers.queryChain(getBaseMapper());
  416. }
  417. /**
  418. * 链式查询 lambda 式
  419. * <p>注意:不支持 Kotlin </p>
  420. *
  421. * @return LambdaQueryWrapper 的包装类
  422. */
  423. default LambdaQueryChainWrapper<T> lambdaQuery() {
  424. return ChainWrappers.lambdaQueryChain(getBaseMapper());
  425. }
  426. /**
  427. * 链式查询 lambda 式
  428. * kotlin 使用
  429. *
  430. * @return KtQueryWrapper 的包装类
  431. */
  432. default KtQueryChainWrapper<T> ktQuery() {
  433. return ChainWrappers.ktQueryChain(getBaseMapper(), getEntityClass());
  434. }
  435. /**
  436. * 链式查询 lambda 式
  437. * kotlin 使用
  438. *
  439. * @return KtQueryWrapper 的包装类
  440. */
  441. default KtUpdateChainWrapper<T> ktUpdate() {
  442. return ChainWrappers.ktUpdateChain(getBaseMapper(), getEntityClass());
  443. }
  444. /**
  445. * 链式更改 普通
  446. *
  447. * @return UpdateWrapper 的包装类
  448. */
  449. default UpdateChainWrapper<T> update() {
  450. return ChainWrappers.updateChain(getBaseMapper());
  451. }
  452. /**
  453. * 链式更改 lambda 式
  454. * <p>注意:不支持 Kotlin </p>
  455. *
  456. * @return LambdaUpdateWrapper 的包装类
  457. */
  458. default LambdaUpdateChainWrapper<T> lambdaUpdate() {
  459. return ChainWrappers.lambdaUpdateChain(getBaseMapper());
  460. }
  461. /**
  462. * <p>
  463. * 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
  464. * 此次修改主要是减少了此项业务代码的代码量(存在性验证之后的saveOrUpdate操作)
  465. * </p>
  466. *
  467. * @param entity 实体对象
  468. */
  469. default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
  470. return update(entity, updateWrapper) || saveOrUpdate(entity);
  471. }
  472. }

        Iservice 中方法非常多,也就说如果我们的servcie 层接口实现了 Iservice,那这些方法等于都已经默认帮我们实现了,所以我们在service层也就可以非常方便的进行增删改查的操作了。简单讲讲增删改查的操作:
        首先根据service层的规范先进行定义service接口,再用serviceImpl去实现service,如下:
        1、定义service接口 并继承 IService:

  1. public interface IUserService extends IService<User> {
  2. }

        2、定义service实现类,并继承ServiceImpl 。

  1. @Service
  2. public class UserService extends ServiceImpl<UserDao, User> implements IUserService {
  3. }

        此时我们就可以使用上面所提供的方法了:

        1、save
  1. User user = new User();
  2. user.setUserName("测试2");
  3. user.setJob("测试工作2");
  4. userService.save(user);
        2、remove
        userService.removeById(user.getId());
      3、update
  1. User user = new User();
  2. user.setUserName("测试3");
  3. user.setJob("测试工作3");
  4. user.setId(1825476862067429378L);
  5. userService.updateById(user);
        4、get
        User user = userService.getById(user.getId());

        上面就是根据主键id进行的增删改查最基础的方法。

        因为IService提供了很多方法,有很多其实应用场景很小,所以下一篇会简单讲讲 其他方法的应用。

五、条件构造器

        BaseMapper 与 Iservice 提供的方法一般只能满足基本的sql语句,如果需要执行复杂的带条件的sql,mybatisplus支持原生的mabatis中的功能,所以如果进行复杂sql,例如多条件动态sql或者多表查询,我们依然可以使用 使用@Servcie、@Update 等注解或者在mapper.xml文件中使用标签书写sql。
        但是其实MybatisPlus中也为我们提供了条件构造器,来执行复杂的多条件动态查询等方法。

        例如通用service常用方法:

  • 新增:
    • default boolean save(T entity):新增记录
    • boolean saveBatch(Collection<T> entityList):批量插入
    • saveBatch(Collection<T> entityList, int batchSize):一次性批量插入batchSize条记录
  • 删除:
    • boolean removeById(Serializable id):根据id删除
    • boolean removeByMap(Map<String, Object> columnMap):根据条件删除
    • boolean remove(Wrapper<T> queryWrapper):使用Wrapper封装条件删除
    • boolean removeByIds(Collection<? extends Serializable> idList):删除一批
  • 修改:
    • boolean updateById(T entity):修改
    • boolean update(Wrapper<T> updateWrapper):根据Wrapper修改
    • boolean update(T entity, Wrapper<T> updateWrapper):使用Wrapper查询出结果,修改为entity
    • boolean updateBatchById(Collection<T> entityList):批量修改
    • updateBatchById(Collection<T> entityList, int batchSize):一次性批量修改batchSize条记录
    • boolean saveOrUpdate(T entity):如果id存在则修改,如果id不存在则新增
  • 查询:
    • T getById(Serializable id):根据id查询
    • List<T> listByIds(Collection<? extends Serializable> idList):根据一批id查询多条记录
    • List<T> listByMap(Map<String, Object> columnMap):根据条件查询多条记录
    • T getOne(Wrapper<T> queryWrapper):根据Wrapper查询一条记录,如果查询到多条则抛出异常
    • T getOne(Wrapper<T> queryWrapper, boolean throwEx):根据Wrapper查询一条记录,通过throwEx决定是否抛出异常
    • int count():查询总记录数
    • int count(Wrapper<T> queryWrapper):根据条件查询总记录数
  • 分页:
    • <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper):带条件分页查询,当前页数据为T类型
    • <E extends IPage<T>> E page(E page):无条件分页
    • List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper):带条件分页查询,当前页数据为HashMap类型
    • List<Map<String, Object>> listMaps():无条件分页

        在有一些方法中的参数类型是 Wrapper<T> queryWrapper ,这个就是条件构造器,例如 

T getOne(Wrapper<T> queryWrapper):根据Wrapper查询一条记录,如果查询到多条则抛出异常

        例如上面这个方法,使用如下所示:

  1. QueryWrapper<User> wrapper = new QueryWrapper<>();
  2. wrapper.eq("name","张三");
  3. User user = userService.getOne(wrapper);

        代表的意思就是查询 name 字段等于张三的数据,并且这条数据必须唯一。
        eq()这个就是Wrapper接口中提供的相关函数,映射在sql语句中的方法是 = ,代表相等。
        除了eq()还提供了其他很多相关映射函数:  

  1、QueryWrapper

  QueryWrapper用于构建查询条件,可以通过链式调用的方式组装各种查询条件。

        QueryWrapper的基本用法:

  1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. public class QueryWrapperExample {
  3. public static void main(String[] args) {
  4. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  5. // 等值条件
  6. queryWrapper.eq("name", "John");
  7. // 不等值条件
  8. queryWrapper.ne("age", 25);
  9. // 大于条件
  10. queryWrapper.gt("create_time", "2022-01-01");
  11. // 小于等于条件
  12. queryWrapper.le("update_time", "2023-01-01");
  13. // 模糊查询
  14. queryWrapper.like("email", "@gmail.com");
  15. // 排序
  16. queryWrapper.orderByAsc("age");
  17. // 使用Lambda表达式
  18. queryWrapper.lambda().eq(User::getName, "Alice");
  19. // 打印SQL语句
  20. System.out.println("SQL: " + queryWrapper.getSqlSelect());
  21. }
  22. }

  Lambda表达式的高级用法:
  QueryWrapper支持Lambda表达式,可以进一步简化代码,提高可读性。

  1. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  2. public class LambdaQueryWrapperExample {
  3.     public static void main(String[] args) {
  4.         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  5.         // Lambda表达式
  6.         queryWrapper.lambda().eq(User::getName, "John")
  7.                              .ne(User::getAge, 25)
  8.                              .like(User::getEmail, "@gmail.com");
  9.         // 打印SQL语句
  10.         System.out.println("SQL: " + queryWrapper.getSqlSelect());
  11.     }
  12. }

如果要使用Lambda表达式的用法,我们也可以直接使用 LambdaQueryWrapper。

        2、LambdaQueryWrapper

        可以把LambdaQueryWrapper看作是实现了Lambda语法的 QueryWrapper,使用方式跟QueryWrapper 一样,只不过可以不用 lambda() 就可以直接使用lambda语法。

  1. LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
  2. wrapper.eq(User::getName,"张三");
  3. User user = userService.getOne(wrapper);
        3、UpdateWrapper

  UpdateWrapper用于构建更新条件,与QueryWrapper类似,也支持链式调用和Lambda表达式。
        注意:在调用更新方法的时候会用到这个。

        基本用法:

  1. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  2. public class UpdateWrapperExample {
  3.     public static void main(String[] args)
  4.  {
  5.         UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
  6.         // 等值条件
  7.         updateWrapper.eq("name", "John");
  8.         // 不等值条件
  9.         updateWrapper.ne("age", 25);
  10.         // 大于条件
  11.         updateWrapper.gt("create_time", "2022-01-01");
  12.         // 小于等于条件
  13.         updateWrapper.le("update_time", "2023-01-01");
  14.         // 模糊查询
  15.         updateWrapper.like("email", "@gmail.com");
  16.         // 使用Lambda表达式
  17.         updateWrapper.lambda().set(User::getName, "Alice").eq(User::getAge, 30);
  18.         // 打印SQL语句
  19.         System.out.println("SQL: " + updateWrapper.getSqlSet());
  20.     }
  21. }

        UpdateWrapper的基本用法与QueryWrapper类似,可以通过链式调用添加等值、不等值、范围、模糊等更新条件。

         Lambda表达式的高级用法:

  1. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  2. public class LambdaUpdateWrapperExample {
  3.     public static void main(String[] args) {
  4.         UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
  5.         // Lambda表达式
  6.         updateWrapper.lambda().set(User::getName, "Alice")
  7.                              .eq(User::getAge, 30)
  8.                              .like(User::getEmail, "@gmail.com");
  9.         // 打印SQL语句
  10.         System.out.println("SQL: " + updateWrapper.getSqlSet());
  11.     }
  12. }

        通过lambda方法,我们可以使用实体类的属性名,使得代码更加简洁和可读。

        4、 LambdaUpdateWrapper

        与LambdaQueryWrapper 一样,用法与UpdateWrapper 也都一样,只是默认实现了Lambda语法。

        条件构造器的详细用法放下下一篇单独写。

六、分页查询

         mybatisplus有自己的内置分页插件,用起来非常方便,不像mybatis还需要引入第三方依赖。

        使用步骤非常简单,只要两步即可:

        1、配置拦截器组件
  1. /**
  2. * 注册插件
  3. */
  4. @Bean
  5. public MybatisPlusInterceptor paginationInterceptor() {
  6.    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  7.    // 添加分页插件
  8.    PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor();
  9.    // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认false
  10.    pageInterceptor.setOverflow(false);
  11.    // 单页分页条数限制,默认无限制
  12.    pageInterceptor.setMaxLimit(500L);
  13.    // 设置数据库类型
  14.    pageInterceptor.setDbType(DbType.MYSQL);
  15.    interceptor.addInnerInterceptor(pageInterceptor);
  16.    return interceptor;
  17. }
        2、直接使用
  1. // 两个参数:current的值默认是1,从1开始,不是0。size是每一页的条数。
  2. // 意思是查询 第一页,每页10条数据
  3. Page<User> page = new Page<>(1, 10);
  4. userMapper.selectPage(page);
  5. page.getRecords().forEach(System.out::println);

        返回结果 第一页 10条数据成功:

         测试第二页 只有一条数据:

七、mybatisplus常用注解

        @TableName

        @TableName注解用于指定实体类对应的数据库表名。使用该注解可以省去手动编写SQL语句的繁琐过程。
        实例:表名为 db_user,对应的实体类 User

  1. @TableName(value = "db_user")
  2. public class User {
  3. // 实体类字段
  4. }
        @TableField

         @TableField是MyBatis-Plus中的注解之一,用于在实体类中指定字段与数据库表中字段的映射关系。通过@TableField注解,可以将实体类中的字段与数据库表中的字段进行映射,从而简化数据访问层的开发。

        @TableField注解提供了多个属性,常用的属性包括:

  • value:指定数据库表字段的名称。用于映射非主键字段,还可以解决关键字报错
  • exist:指定该字段是否为数据库表字段,默认为true。是否忽略该字段
  • fill:指定字段填充策略,如插入时自动填充、更新时自动填充等。自动填充,将对象存入数据库的时候,由 MyBatis Plus 自动给某些字段赋值,例如:create_time、update_time
  • select:指定该字段是否参与查询,默认为true。是否查询该字段
  • update: 预处理set字段自定义注入
  • condition:指定该字段在查询条件中的匹配方式,如LIKE、EQUAL等。

        示例:

  1. @Data
  2. @TableName(value = "student")
  3. public class Student {
  4. @TableId
  5. private Long id;
  6. // 当该字段名称与数据库名字不一致
  7. @TableField(value = "name")
  8. private String name;
  9. // 不查询该字段
  10. @TableField(select = false)
  11. private Integer age;
  12. // 当数据库中没有该字段,就忽略
  13. @TableField(exist = false)
  14. private String gender;
  15. // 执行的sql语句就变成`关键字`,这样sql就不会报错了
  16. @TableField(value = "`desc`")
  17. private string desc
  18. // 第一次添加填充
  19. @TableField(fill = FieldFill.INSERT)
  20. private Date createTime;
  21. // 第一次添加的时候填充,但之后每次更新也会进行填充
  22. @TableField(fill = FieldFill.INSERT_UPDATE)
  23. private Date updateTime;
  24. }

        自动填充演示:

        1、第一步像上面一样先添加注解,@TableField(fill = FieldFill.INSERT) 代表当数据第一次添加时更新,@TableField(fill = FieldFill.INSERT_UPDATE) 代表数据添加或者更新时都更新该字段。
        2、创建自动填充处理器

  1. // 加入注解才能生效
  2. @Component
  3. public class MyMetaObjectHandler implements MetaObjectHandler {
  4. @Override
  5. public void insertFill(MetaObject metaObject) {
  6. this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
  7. this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
  8. }
  9. @Override
  10. public void updateFill(MetaObject metaObject) {
  11. this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
  12. }
  13. }

        3、测试就忽略了,可以自己试一下当调用update和save的方法时就会自动填充或者更新该字段。

        condition 预处理演示:

  1. /**
  2. * 角色名称
  3. */
  4. @TableField(condition = SqlCondition.LIKE)
  5. private String name;
  6. 输出 SQL 为:select 表 where name LIKE CONCAT('%',值,'%')

        意思是说当我们将实体类的这个字段加上这个注解时,在使用该实体类作为条件 构建条件构造器时,会自动为我们拼接一个模糊查询的条件。

        例如:

  1. User user = new User();
  2. user.setName("张三");
  3. LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>(user);
  4. System.out.println(userService.list(wrapper));

 

         update 预处理set字段:

         比如我们使用mybatisplus自带的insert()方法向数据库插入数据时,假设我们给age字段赋值为1,但是我们在age字段上的@TableField注解里面加了update="%s+1",那么真真插入到数据库的值就是age=2,而不是age+1了)

  1. 例如:@TableField(.. , update="%s+1") 其中 %s 会填充为字段
  2. 输出 SQL 为:updateset 字段=字段+1 where ...

        如果给某个字段上@TableField注解里面写update=“now()”,那么最后我们使用mybatisplus自带的insert()方法向数据库插入数据时,这个字段插入到数据库中的值就为当前时间,看下面代码的sql语句即可明白

  1. 例如:@TableField(.. , update="now()") 使用数据库时间
  2. 输出 SQL 为:updateset 字段=now() where ...
        @TableId

        作用:用于标记实体类属性对应的数据库主键。

        @TableId是MyBatis-Plus中的注解之一,用于在实体类中指定主键与数据库表中主键的映射关系。通过@TableId注解,可以将实体类中的主键与数据库表中的主键进行映射,从而简化数据访问层的开发。

        使用@TableId注解时,可以指定主键的属性,例如主键的类型、是否为自增、是否为全局唯一标识符等

        试例:

  1. public class User {
  2. @TableId(value = "id", type = IdType.ASSIGN_ID)
  3. private Long id;
  4. // 省略getter和setter方法
  5. }

   value 映射主键字段名 ,type 设置主键类型,主键的生成策略。type有五个常用属性:

     (1)NONE,默认的,数据库主键id自增,使用雪花算法实现,实体类中的主键应设置为long类型,避免生成的主键id长度过长而溢出
(2)input,如果开发者手动赋值,则存入该值,如果开发者没有手动赋值,则数据库通过自增方式给主键赋值
(3)AUTO默认就是数据库自增,开发者无需赋值,如果开发者手动赋值,数据库也不会存入该值
(4)ASSIGN_ID,通过雪花算法自动生成id,生成主键非自增
(5)ASSIGN_UUID,主键类型必须为String类型,雪花算法自动生成
要求数据库字段类型,实体类型必须为String

  • 在某些情况下,我们想提前获取这个ID,调用com.baomidou.mybatisplus.core.toolkit.IdWorker.getId()方法即可

        @TableLogic

        映射逻辑删除,并不是真正的删除

1、数据表添加 deleted 字段,默认是0

2、实体类添加注解

  1. package com.md.entity;
  2. import com.baomidou.mybatisplus.annotation.*;
  3. import com.md.enums.StatusEnum;
  4. import lombok.Data;
  5. import java.util.Date;
  6. @Data
  7. @TableName(value = "student")
  8. public class Student {
  9. @TableId
  10. private Long id;
  11. @TableField(value = "name")
  12. private String name;
  13. @TableField(select = false)
  14. private Integer age;
  15. @TableField(exist = false)
  16. private String gender;
  17. @TableField(fill = FieldFill.INSERT)
  18. private Date createTime;
  19. @TableField(fill = FieldFill.INSERT_UPDATE)
  20. private Date updateTime;
  21. @Version
  22. private Integer version;
  23. private StatusEnum status;
  24. @TableLogic
  25. private Integer deleted;
  26. }

3、主配置文件中添加配置

  1. # 没有删除为0,删除了为1
  2. mybatis-plus:
  3. global-config:
  4. db-config:
  5. logic-not-delete-value: 0
  6. logic-delete-value: 1

        删除的时候不是真正的删除数据库表中的数据,而是改变delete字段的值,当然了查询的时候也是查询delete=0,这都是框架自动实现的

本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号