若依框架使用—MybatisPlus中动态sql语句详解
MybatisPlus中动态sql语句主要涉及到两个属性ew.getSqlSelect和ew.getCustomSqlSegment。
ew.getSqlSelect主要用于拼接select后面的语句
ew.getCustomSqlSegment用于拼接Where后面的语句
代码实现
Service层
@Override
public TableDataInfo<DeviceChannelVo> queryPageList(DeviceChannelBo deviceChannelBo, PageQuery pageQuery) {
LambdaQueryWrapper<DeviceChannel> lqw = buildQueryWrapper(deviceChannelBo);
Page<DeviceChannelVo> result = baseMapper.selectVoPageList(pageQuery.build(),lqw);
return TableDataInfo.build(result);
}
private LambdaQueryWrapper<DeviceChannel> buildQueryWrapper(DeviceChannelBo bo) {
LambdaQueryWrapper<DeviceChannel> lqw = Wrappers.lambdaQuery();
//配合ew.getSqlSelect使用
lqw.select(DeviceChannel::getId,DeviceChannel::getDeviceId,DeviceChannel::getChannelId,DeviceChannel::getName);
//配合ew.getCustomSqlSegment使用
lqw.eq(StringUtils.isNotBlank(bo.getDeviceId()), DeviceChannel::getDeviceId, bo.getDeviceId());
lqw.eq(StringUtils.isNotBlank(bo.getChannelId()), DeviceChannel::getChannelId, bo.getChannelId());
lqw.like(StringUtils.isNotBlank(bo.getName()), DeviceChannel::getName, bo.getName());
lqw.eq(bo.getStatus() != null, DeviceChannel::getStatus, bo.getStatus());
return lqw;
}
Mapper层
@Mapper
public interface DeviceChannelMapper extends BaseMapperPlus<DeviceChannel, DeviceChannelVo> {
Page<DeviceChannelVo> selectVoPageList(@Param("page") Page<DeviceChannelVo> page,@Param(Constants.WRAPPER) Wrapper<DeviceChannel> queryWrapper);
}
XML层
<select id="selectVoPageList" resultMap="DeviceChannelResult">
select
<if test="ew.getSqlSelect != null">
${ew.getSqlSelect}
</if>
<if test="ew.getSqlSelect == null">
id, T1.channelId, T1.deviceId, name, T2.dept_id
</if>
FROM device_channel T1
LEFT JOIN dept_device T2
ON T1.deviceId = T2.device_id AND T1.channelId = T2.channel_id
${ew.getCustomSqlSegment}
ORDER BY T1.id
</select>
相关源码
条件构造抽象类Wrapper
/*
* Copyright (c) 2011-2024, baomidou ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.baomidou.mybatisplus.core.conditions;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.conditions.segments.NormalSegmentList;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.*;
import java.util.Objects;
/**
* 条件构造抽象类
*
* @author hubin
* @since 2018-05-25
*/
@SuppressWarnings("all")
public abstract class Wrapper<T> implements ISqlSegment {
/**
* 实体对象(子类实现)
*
* @return 泛型 T
*/
public abstract T getEntity();
public String getSqlSelect() {
return null;
}
public String getSqlSet() {
return null;
}
public String getSqlComment() {
return null;
}
public String getSqlFirst() {
return null;
}
/**
* 获取 MergeSegments
*/
public abstract MergeSegments getExpression();
/**
* 获取自定义SQL 简化自定义XML复杂情况
* <p>
* 使用方法: `select xxx from table` + ${ew.customSqlSegment}
* <p>
* 注意事项:
* 1. 逻辑删除需要自己拼接条件 (之前自定义也同样)
* 2. 不支持wrapper中附带实体的情况 (wrapper自带实体会更麻烦)
* 3. 用法 ${ew.customSqlSegment} (不需要where标签包裹,切记!)
* 4. ew是wrapper定义别名,不能使用其他的替换
*/
public String getCustomSqlSegment() {
MergeSegments expression = getExpression();
if (Objects.nonNull(expression)) {
NormalSegmentList normal = expression.getNormal();
String sqlSegment = getSqlSegment();
if (StringUtils.isNotBlank(sqlSegment)) {
if (normal.isEmpty()) {
return sqlSegment;
} else {
return Constants.WHERE + StringPool.SPACE + sqlSegment;
}
}
}
return StringPool.EMPTY;
}
/**
* 查询条件为空(包含entity)
*/
public boolean isEmptyOfWhere() {
return isEmptyOfNormal() && isEmptyOfEntity();
}
/**
* 查询条件不为空(包含entity)
*/
public boolean isNonEmptyOfWhere() {
return !isEmptyOfWhere();
}
@Deprecated
public boolean nonEmptyOfWhere() {
return isNonEmptyOfWhere();
}
/**
* 查询条件为空(不包含entity)
*/
public boolean isEmptyOfNormal() {
return CollectionUtils.isEmpty(getExpression().getNormal());
}
/**
* 查询条件为空(不包含entity)
*/
public boolean isNonEmptyOfNormal() {
return !isEmptyOfNormal();
}
@Deprecated
public boolean nonEmptyOfNormal() {
return isNonEmptyOfNormal();
}
/**
* 深层实体判断属性
*
* @return true 不为空
*/
public boolean isNonEmptyOfEntity() {
T entity = getEntity();
if (entity == null) {
return false;
}
TableInfo tableInfo = TableInfoHelper.getTableInfo(entity.getClass());
if (tableInfo == null) {
return false;
}
if (tableInfo.getFieldList().stream().anyMatch(e -> fieldStrategyMatch(tableInfo, entity, e))) {
return true;
}
return StringUtils.isNotBlank(tableInfo.getKeyProperty()) ? Objects.nonNull(tableInfo.getPropertyValue(entity, tableInfo.getKeyProperty())) : false;
}
@Deprecated
public boolean nonEmptyOfEntity() {
return isNonEmptyOfEntity();
}
/**
* 根据实体FieldStrategy属性来决定判断逻辑
*/
private boolean fieldStrategyMatch(TableInfo tableInfo, T entity, TableFieldInfo e) {
switch (e.getWhereStrategy()) {
case NOT_NULL:
return Objects.nonNull(tableInfo.getPropertyValue(entity, e.getProperty()));
case IGNORED:
return true;
case ALWAYS:
return true;
case NOT_EMPTY:
return StringUtils.checkValNotNull(tableInfo.getPropertyValue(entity, e.getProperty()));
case NEVER:
return false;
default:
return Objects.nonNull(tableInfo.getPropertyValue(entity, e.getProperty()));
}
}
/**
* 深层实体判断属性
*
* @return true 为空
*/
public boolean isEmptyOfEntity() {
return !isNonEmptyOfEntity();
}
/**
* 获取格式化后的执行sql
*
* @return sql
* @since 3.3.1
*/
public String getTargetSql() {
return getSqlSegment().replaceAll("#\\{.+?}", "?");
}
/**
* 条件清空
*
* @since 3.3.1
*/
abstract public void clear();
}
自用常量集中管理Constants
/*
* Copyright (c) 2011-2024, baomidou ([email protected]).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.baomidou.mybatisplus.core.toolkit;
import java.io.Serializable;
/**
* mybatis_plus 自用常量集中管理
*
* @author miemie
* @since 2018-07-22
*/
public interface Constants extends StringPool, Serializable {
/**
* project name
*/
String MYBATIS_PLUS = "mybatis-plus";
/**
* MD5
*/
String MD5 = "MD5";
/**
* AES
*/
String AES = "AES";
/**
* AES 算法
*/
String AES_CBC_CIPHER = "AES/CBC/PKCS5Padding";
/**
* as
*/
String AS = " AS ";
/**
* 实体类
*/
String ENTITY = "et";
/**
* 实体类 带后缀 ==> .
*/
String ENTITY_DOT = ENTITY + DOT;
/**
* wrapper 类
*/
String WRAPPER = "ew";
/**
* wrapper 类 带后缀 ==> .
*/
String WRAPPER_DOT = WRAPPER + DOT;
/**
* wrapper 类的属性 entity
*/
String WRAPPER_ENTITY = WRAPPER_DOT + "entity";
/**
* wrapper 类的属性 sqlSegment
*/
String WRAPPER_SQLSEGMENT = WRAPPER_DOT + "sqlSegment";
/**
* wrapper 类的属性 emptyOfNormal
*/
String WRAPPER_EMPTYOFNORMAL = WRAPPER_DOT + "emptyOfNormal";
/**
* wrapper 类的属性 nonEmptyOfNormal
*/
String WRAPPER_NONEMPTYOFNORMAL = WRAPPER_DOT + "nonEmptyOfNormal";
/**
* wrapper 类的属性 nonEmptyOfEntity
*/
String WRAPPER_NONEMPTYOFENTITY = WRAPPER_DOT + "nonEmptyOfEntity";
/**
* wrapper 类的属性 emptyOfWhere
*/
String WRAPPER_EMPTYOFWHERE = WRAPPER_DOT + "emptyOfWhere";
/**
* wrapper 类的判断属性 nonEmptyOfWhere
*/
String WRAPPER_NONEMPTYOFWHERE = WRAPPER_DOT + "nonEmptyOfWhere";
/**
* wrapper 类的属性 entity 带后缀 ==> .
*/
String WRAPPER_ENTITY_DOT = WRAPPER_DOT + "entity" + DOT;
/**
* wrapper 类的属性 expression 下级属性 order
*/
String WRAPPER_EXPRESSION_ORDER = WRAPPER_DOT + "useAnnotationOrderBy";
/**
* UpdateWrapper 类的属性 sqlSet
*/
String U_WRAPPER_SQL_SET = WRAPPER_DOT + "sqlSet";
/**
* QueryWrapper 类的属性 sqlSelect
*/
String Q_WRAPPER_SQL_SELECT = WRAPPER_DOT + "sqlSelect";
/**
* wrapper 类的属性 sqlComment
*/
String Q_WRAPPER_SQL_COMMENT = WRAPPER_DOT + "sqlComment";
/**
* wrapper 类的属性 sqlFirst
*/
String Q_WRAPPER_SQL_FIRST = WRAPPER_DOT + "sqlFirst";
/**
* columnMap
*/
@Deprecated
String COLUMN_MAP = "cm";
/**
* columnMap.isEmpty
*/
String COLUMN_MAP_IS_EMPTY = COLUMN_MAP + DOT + "isEmpty";
/**
* collection
*
* @see #COLL
* @deprecated 3.5.2 后面修改成collection
*/
@Deprecated
String COLLECTION = "coll";
/**
* @since 3.5.2
*/
String COLL = "coll";
/**
* list
*
* @since 3.5.0
*/
String LIST = "list";
/**
* where
*/
String WHERE = "WHERE";
/**
* limit
*/
String LIMIT = "LIMIT";
/**
* @since 3.5.2
*/
String ARRAY = "array";
/**
* order by
*/
String ORDER_BY = "ORDER BY";
/**
* asc
*/
String ASC = "ASC";
/**
* desc
*/
String DESC = "DESC";
/**
* 乐观锁字段
*/
String MP_OPTLOCK_VERSION_ORIGINAL = "MP_OPTLOCK_VERSION_ORIGINAL";
/**
* wrapper 内部参数相关
*/
String WRAPPER_PARAM = "MPGENVAL";
String WRAPPER_PARAM_MIDDLE = ".paramNameValuePairs" + DOT;
/**
* 默认批次提交数量
*/
int DEFAULT_BATCH_SIZE = 1000;
}