本文介绍springboot整合mybatis-plus在项目中使用时,写查询方法的时候,使用lambda表示查询数据,在真正执行sql的时候where条件会拼接deleted = 0 。

原因:1、全局配置配置删除字段。默认删除值=1.未删除值=0。配置方式如下:

mybatis-plus.global-config.db-config.logic-delete-field = deleted

在使用全局配置的时候,如果实体类中有deleted字段,就会拼接deleted = 0.

2. 如果全局没有配置,在实体类中单独使用代码

@Data
@Accessors(chain = true)
@TableName("order")
public class Order {@ApiModelProperty(value = "主键ID")@TableId(value = "id", type = IdType.AUTO)private Long id;@TableLogic(value = "0",delval = "1")@ApiModelProperty(value = "是否已删除, 1:是, 0:否")private Integer deleted;}

这也可以生效,如果,想灵活使用deleted = 0 ,自己决定是否在查询中拼接deleted = 0。那么就不能使用全局配置,自己在查询时,如果实体类中逻辑删除字段,就会拼接,没有就不会拼接,执行删除的时候,也需要自己设置deleted 的值。

源码分析:

代码1

public class TableInfoHelper {
//  省略代码,下面这是私有方法,大家可以往上找,看各方法的功能/*** <p>* 初始化 表主键,表字段* </p>** @param clazz        实体类* @param globalConfig 全局配置* @param tableInfo    数据库表反射信息*/private static void initTableFields(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo, List<String> excludeProperty) {/* 数据库全局配置 */GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();Reflector reflector = tableInfo.getReflector();List<Field> list = getAllFields(clazz);// 标记是否读取到主键boolean isReadPK = false;// 是否存在 @TableId 注解boolean existTableId = isExistTableId(list);// 是否存在 @TableLogic 注解boolean existTableLogic = isExistTableLogic(list);List<TableFieldInfo> fieldList = new ArrayList<>(list.size());for (Field field : list) {if (excludeProperty.contains(field.getName())) {continue;}
// 该字段是否是主键,默认FALSE,下面赋值boolean isPK = false;boolean isOrderBy = field.getAnnotation(OrderBy.class) != null;/* 主键ID 初始化 */if (existTableId) {TableId tableId = field.getAnnotation(TableId.class);if (tableId != null) {if (isReadPK) {throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());}// 有主键,设置主键生成方法,主键名字initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId);
//  这只是主键为trueisPK = isReadPK = true;}} else if (!isReadPK) {isPK = isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field);}if (isPK) {if (isOrderBy) {tableInfo.getOrderByFields().add(new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic, true));}continue;}final TableField tableField = field.getAnnotation(TableField.class);/* 有 @TableField 注解的字段初始化 */if (tableField != null) {
//  注意看new TableFieldInfo()这个构造方法,执行的时候,会判断字段是否有@TableLogic注解,没有,看全局配置,
//  existTableLogic这个参数是整个实体类中是否有@TableLogic注解fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, tableField, reflector, existTableLogic, isOrderBy));continue;}/* 无 @TableField  注解的字段初始化 */fieldList.add(new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic, isOrderBy));}/* 字段列表 */tableInfo.setFieldList(fieldList);/* 未发现主键注解,提示警告信息 */if (!isReadPK) {logger.warn(String.format("Can not find table primary key in Class: \"%s\".", clazz.getName()));}}
}

看代码

new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic, isOrderBy)

这个TableFieldInfo构造方法中,会调用this(...),在调用

this.initLogicDelete(dbConfig, field, existTableLogic);

代码2

private void initLogicDelete(GlobalConfig.DbConfig dbConfig, Field field, boolean existTableLogic) {/* 获取注解属性,逻辑处理字段 */TableLogic tableLogic = field.getAnnotation(TableLogic.class);if (null != tableLogic) {if (StringUtils.isNotBlank(tableLogic.value())) {this.logicNotDeleteValue = tableLogic.value();} else {this.logicNotDeleteValue = dbConfig.getLogicNotDeleteValue();}if (StringUtils.isNotBlank(tableLogic.delval())) {this.logicDeleteValue = tableLogic.delval();} else {this.logicDeleteValue = dbConfig.getLogicDeleteValue();}this.logicDelete = true;} else if (!existTableLogic) {
// 实体类中没有标记TableLogic注解,existTableLogic这个值=false,!existTableLogic=true,就会进入这个方法String deleteField = dbConfig.getLogicDeleteField();
// 上边获取全局的删除字段名称
// 下面判断字段名称和全局定义的一样,就赋值if (StringUtils.isNotBlank(deleteField) && this.property.equals(deleteField)) {this.logicNotDeleteValue = dbConfig.getLogicNotDeleteValue();this.logicDeleteValue = dbConfig.getLogicDeleteValue();this.logicDelete = true;}}}

在代码1方法中,tableInfo.setFieldList(fieldList);这行代码会调用tableInfo类的方法,

代码3

void setFieldList(List<TableFieldInfo> fieldList) {this.fieldList = fieldList;AtomicInteger logicDeleted = new AtomicInteger();AtomicInteger version = new AtomicInteger();fieldList.forEach(i -> {
// 在上边代码2中删除字段的isLogicDelete会赋值trueif (i.isLogicDelete()) {
// 这里会设置withLogicDelete=true,this.withLogicDelete = true;
// 设置删除字段this.logicDeleteFieldInfo = i;logicDeleted.getAndAdd(1);}if (i.isWithInsertFill()) {this.withInsertFill = true;}if (i.isWithUpdateFill()) {this.withUpdateFill = true;}if (i.isOrderBy()) {if (null == this.orderByFields) {this.orderByFields = new LinkedList<>();}this.orderByFields.add(i);}if (i.isVersion()) {this.withVersion = true;this.versionFieldInfo = i;version.getAndAdd(1);}});/* 校验字段合法性 */Assert.isTrue(logicDeleted.get() <= 1, "@TableLogic not support more than one in Class: \"%s\"", entityType.getName());Assert.isTrue(version.get() <= 1, "@Version not support more than one in Class: \"%s\"", entityType.getName());}

等调用查询方法的时候,拼接sql时会调用

public class TableInfo{/*** 获取逻辑删除字段的 sql 脚本** @param startWithAnd 是否以 and 开头* @param isWhere      是否需要的是逻辑删除值* @return sql 脚本*/public String getLogicDeleteSql(boolean startWithAnd, boolean isWhere) {
// 如果类中有删除字段,标记了@TableLogic注解,或者字段和全局一样,withLogicDelete在代码3中已经
// 赋值=true,就会进入下面的拼接deleted = 0 方法if (withLogicDelete) {String logicDeleteSql = formatLogicDeleteSql(isWhere);if (startWithAnd) {logicDeleteSql = " AND " + logicDeleteSql;}return logicDeleteSql;}return EMPTY;}/*** format logic delete SQL, can be overrided by subclass* github #1386** @param isWhere true: logicDeleteValue, false: logicNotDeleteValue* @return sql*/
// 真正拼接的方法protected String formatLogicDeleteSql(boolean isWhere) {final String value = isWhere ? logicDeleteFieldInfo.getLogicNotDeleteValue() : logicDeleteFieldInfo.getLogicDeleteValue();if (isWhere) {if (NULL.equalsIgnoreCase(value)) {return logicDeleteFieldInfo.getColumn() + " IS NULL";} else {return logicDeleteFieldInfo.getColumn() + EQUALS + String.format(logicDeleteFieldInfo.isCharSequence() ? "'%s'" : "%s", value);}}final String targetStr = logicDeleteFieldInfo.getColumn() + EQUALS;if (NULL.equalsIgnoreCase(value)) {return targetStr + NULL;} else {return targetStr + String.format(logicDeleteFieldInfo.isCharSequence() ? "'%s'" : "%s", value);}}
}

如果在查询的sql中想不拼接deleted = 0 ,解决方法:

1. 不设置全局逻辑删除字段,如果有逻辑删除,自己在代码中定义删除字段,并标记@TableLogic注解,里面可以写删除的值,和不删除的值。如果设置全局删除字段,适用于,删除场景比较少,查询比较的多的。并且项目中采用的是逻辑删除。

2.如果设置了全局的删除字段,实体类中定义的删除字段与全局的不一样。如果自己在那个字段上加@TableLogic注解,代码查询就会拼接删除=0条件,不加注解,就自己设置。

3. 如果项目查询比较多,都是采用逻辑删除,在查询的时候需要查出删除数据,就需要自己写xml的sql语句。其他lambda表达式的查询,由mybatis自动加上deleted = 0条件。

mybatis-plus查询sql条件拼接deleted = 0相关推荐

  1. java中模糊查询sql怎么写,mybatis模糊查询sql,

    mybatis模糊查询sql, 今天下午做的一个功能,要用到模糊查询,字段是description,刚开始我的写法用的是sql中的模糊查询语句, 但是这个有问题,只有将字段的全部值传入其中,才能查询, ...

  2. 【问题解决】MyBatis分页查询SQL Server2008时出现'@P0' 附近有语法错误

    MyBatis分页查询SQL Server2008时出现'@P0' 附近有语法错误" Error querying database. Cause: com.microsoft.sqlser ...

  3. Mybatis模糊查询SQL语句

    模糊查询 <sql id="where_case"><if test="username!=null and username != ''"& ...

  4. mybatis模糊查询sql

    今天下午做的一个功能,要用到模糊查询,字段是description,刚开始我的写法用的是sql中的模糊查询语句, 但是这个有问题,只有将字段的全部值传入其中,才能查询,所以不是迷糊查询. 后来经过搜索 ...

  5. mybatis通用的多条件筛选查询

    在开发项目阶段中为了方便往后的维护与灵活使用,做一个通用的查询功能比较便捷.在mybatis里面动态的拼接sql完成多条件查询,一些特殊字符可以采用一些其他代码代替. 封装格式如下 [{"a ...

  6. 达梦查询sql优化几种方式

    问题描述 在近做项目的过程中遇到了达梦查询sql 性能过慢问题,把平常在MySQL和Oracle中一些优化方法拿到达梦这边来使用,发现效果是比较小的,最终通过查阅资料发现了达梦优化sql的方式和MyS ...

  7. mybatis plus条件拼接

    mybatis plus条件拼接 条件构造器 案例table AbstractWrapper allEq:全部eq(或个别isNull) eq:等于 = ne:不等于 <> gt:大于 & ...

  8. MyBatis 实践 -动态SQL/关联查询

    MyBatis 实践 标签: Java与存储 动态SQL 动态SQL提供了对SQL语句的灵活操作,通过表达式进行判断,对SQL进行拼接/组装. if 对查询条件进行判断,如果输入参数不为空才进行查询条 ...

  9. Mybatis——注入执行sql查询、更新、新增以及建表语句

    文章目录 前言 案例 dao和mapper编写 XXXmapper.xml编写 编写业务层代码,进行注入调用 额外扩展--创建表语句 前言 在平时的项目开发中,mybatis应用非常广泛,但一般都是直 ...

最新文章

  1. 直播APP常用动画效果
  2. 4一20ma电流有源与无源区别_信号隔离安全栅与信号隔离器区别!
  3. 美国多个城市禁止、我国却蓬勃发展的人脸识别是什么样子?
  4. windows stack based overflow
  5. 武大计算机宿舍,国内最“豪华”的4所大学宿舍,武大上榜,最后一所意想不到!...
  6. 35修改tomcat端口
  7. mysql 5.7.20 win64_Win10下MySQL5.7.20 Mysql(64位)解压版安装及bug修复
  8. 擅长排列的小明(nyoj19)
  9. 求python一个类与对象的代码_Python基础系列(五)类和对象,让你更懂你的python代码...
  10. 如何快速掌握man手册的使用
  11. PHP for 循环
  12. 零起点英语_【零起点英语】第100讲:The Cost of War 战争的代价
  13. Android时间戳与字符串相互转换
  14. java jxdatepicker_在Java Swingx中修剪JXDatePicker
  15. linux中配置vsftpd
  16. 计算机word怎么设置页眉,Word怎么设置长文档的页眉页脚?_计算机办公软件知识...
  17. php中fastcgi和php-fpm是什么
  18. html5canvas下绘制gif,JS+canvas操作gif动图
  19. java的 violate 和 synchronize
  20. Ubuntu 20.04 Desktop 设置桌面图标大小、间距

热门文章

  1. H5微信分享接口开发JS-SDK PHP[附源码]
  2. 如何注册股份有限公司,股份有限公司注册的资本最低限额是多少?
  3. C语言之函数指针与指针函数
  4. popstate_图解用HTML5的popstate如何玩转浏览器历史记录
  5. C#中的using关键字
  6. 我失业了?D西门子大裁员始末
  7. 鸿蒙系统不支持天玑芯片吗,华为鸿蒙 OS 2.0 手机更新官方适配计划曝光:支持 Mate X2/Mate 40/P40 系列等,联发科天玑机型可能无缘...
  8. html图像粒子转换动画,html5 canvas粒子动画生成图片特效
  9. 数据流图和软件结构图
  10. U盘安装CentOS7出现问题的解决方案