- 单表:Mybatis-Plus分页
- 单表:Plus的CRUD规范
- 单表:补充计数方法
- 单表:条件构造器Wrapper
- #allEq">#allEq
- #eq">#eq
- #ne">#ne
- #gt">#gt
- #ge">#ge
- #lt">#lt
- #le">#le
- #between">#between
- #notBetween">#notBetween
- #like">#like
- #notLike">#notLike
- #likeLeft">#likeLeft
- #likeRight">#likeRight
- #isNull">#isNull
- #isNotNull">#isNotNull
- #in">#in
- #notIn">#notIn
- #inSql">#inSql
- #notInSql">#notInSql
- #groupBy">#groupBy
- #orderByAsc">#orderByAsc
- #orderByDesc">#orderByDesc
- #orderBy">#orderBy
- #having">#having
- #func">#func
- #or">#or
- #and">#and
- #nested">#nested
- #apply">#apply
- #last">#last
- #exists">#exists
- #notExists">#notExists
单表:Mybatis-Plus分页
单表查询时建议使用:借助的是Page
类与Wrapper
接口实现
单表分页:在IService
里有分页查询接口叫Page<T> selectPage(Page<T> page);
和Page<T> selectPage(Page<T> page, Wrapper<T> wrapper);
/**
* <p>
* 顶级 Service
* </p>
*
* @author hubin
* @Date 2016-04-20
*/
public interface IService<T> {
/**
* <p>
* 翻页查询
* </p>
*
* @param page 翻页对象
* @return
*/
Page<T> selectPage(Page<T> page);
/**
* <p>
* 翻页查询
* </p>
*
* @param page 翻页对象
* @param wrapper 实体包装类 {@link Wrapper}
* @return
*/
Page<T> selectPage(Page<T> page, Wrapper<T> wrapper);
}
由于是单表查询,不需定义连接查询的Mapper,用IService的Page<T> selectPage(Page<T> page, Wrapper<T> wrapper);即可
@Override
public PageInfo<MsgLogConditionResponse> msgLogs(MsgLogConditionRequest msgLogConditionRequest) {
Page page = new Page<>((msgLogConditionRequest.getCurrent() == null ? 1 : msgLogConditionRequest.getCurrent()), (msgLogConditionRequest.getSize() == null ? 10 : msgLogConditionRequest.getSize()));
Boolean unRead = msgLogConditionRequest.getUnRead();
String sceneType = msgLogConditionRequest.getSceneType();
System.out.println("sceneType:"+sceneType);
//分页列表SQL,if-test控制是否执行过滤
Page resPage = selectPage(page, new EntityWrapper<MsgLog>()
.eq(unRead, MsgLog.CONST_MSG_STATE, MsgLog.HAVED_NO_READ)
.eq(StringUtils.isNotBlank(sceneType), MsgLog.CONST_SCENE_TYPE, sceneType)
.eq(MsgLog.CONST_STATUS, MsgLog.DELETE_STATUS_VALIDATED));
List<MsgLog> records = resPage.getRecords();
ArrayList<MsgLogConditionResponse> responses = new ArrayList<>();
for (MsgLog msgLog : records) {
MsgLogConditionResponse msgLogConditionResponse = new MsgLogConditionResponse();
msgLogConditionResponse.setMsgContent(msgLog.getMsgContent());
msgLogConditionResponse.setReceiveTime(msgLog.getReceiveTime());
msgLogConditionResponse.setSceneType(msgLog.getSceneType());
msgLogConditionResponse.setMsgStatus(msgLog.getMsgState());
responses.add(msgLogConditionResponse);
}
return new PageInfo<>(page.getCurrent(), page.getSize(), page.getTotal(), responses);
}
遇到连表分页就自定义连接查询的Mapper
,即手写SQL
public interface VmInstanceApplicationMapper extends BaseMapper<VmInstanceApplication> {
/**
* 申请列表
* @param page
* @param params
* @return
*/
List<VmInstanceApplicationResponse> applicationList(Page page, VmInstanceApplicationRequest params);
}
#SQL无需手动分页了
<select id="applicationList" parameterType="com.iwhalecloud.aiFactory.aiDevCenter.application.vo.VmInstanceApplicationRequest" resultType="com.iwhalecloud.aiFactory.aiDevCenter.application.vo.VmInstanceApplicationResponse">
SELECT
vm.name vmName,
t.id, t.vm_instance, t.duration, t.application_desc, t.create_user_id, t.create_time, t.auditor, t.audit_desc, t.audit_time, t.com_acct_id, t.application_status
FROM
vm_instance_application t
LEFT JOIN vm_instance vm ON t.vm_instance = vm.id
WHERE
1 = 1
<if test="createUserId != null">
AND t.create_user_id = #{createUserId}
</if>
<if test="applicationStatus != null and applicationStatus != ''">
AND t.application_status = #{applicationStatus}
</if>
<if test="vmName != null and vmName != ''">
AND vm.name LIKE concat('%', #{vmName}, '%')
</if>
<if test="vmInstance != null">
AND t.vm_instance = #{vmInstance}
</if>
<if test="comAcctId != null">
AND t.com_acct_id = #{comAcctId}
</if>
<if test="applicationStatusList != null and applicationStatusList.size() > 0">
AND t.application_status in
<foreach collection="applicationStatusList" item="one" open="(" close=")" separator=",">
#{one}
</foreach>
</if>
ORDER BY
create_time DESC
</select>
单表:Plus的CRUD规范
单操作|条件操作|批量操作使用规范:
BaseMapper
只有单条插入,在IService
里有批量插入接口叫insertBatch
BaseMapper
只有单条删除,在IService
里有批量删除接口叫deleteBatchIds
BaseMapper
只有单条修改,在IService
里有批量删除接口叫updateBatchById
- 其实
BaseMapper
里面的条件删除,条件修改也可以构造批量操作条件,但是直接使用IService
里面现成的批量操作更方便,推荐!
BaseMapper
里面的条件查询十分好用List<T> selectList(@Param("ew") Wrapper<T> wrapper);
IService
里的批量ids
查询很方便List<T> selectBatchIds(Collection<? extends Serializable> idList);
增
单增
public interface BaseMapper<T> {
/**
* <p>
* 插入一条记录
* </p>
*
* @param entity 实体对象
* @return int
*/
Integer insert(T entity);
}
返回ID
```java MyBatis-Plus 新增插入成功并返回自增Id:调用完insert方法后,直接 entity.getId() 即可
taiModelChangeMapper.insert(taiModelChange); //得到mybatis-plus的自增id Integer id = taiModelChange.getId(); System.out.println(“得到mybatis-plus的自增id “+id);
<a name="MWnGV"></a>
### 批量增
`BaseMapper`只有单条插入,在`IService`里有批量插入接口叫`insertBatch`
```shell
public interface IService<T> {
/**
* <p>
* 插入(批量),该方法不适合 Oracle
* </p>
*
* @param entityList 实体对象列表
* @return boolean
*/
boolean insertBatch(List<T> entityList);
}
删
单删deleteById
public interface BaseMapper<T> {
/**
* <p>
* 根据 ID 删除
* </p>
*
* @param id 主键ID
* @return int
*/
Integer deleteById(Serializable id);
}
条件删
public interface BaseMapper<T> {
/**
* <p>
* 根据 entity 条件,删除记录
* </p>
*
* @param wrapper 实体对象封装操作类(可以为 null)
* @return int
*/
Integer delete(@Param("ew") Wrapper<T> wrapper);
}
批量删
BaseMapper
只有单条删除,在IService
里有批量删除接口叫deleteBatchIds
public interface IService<T> {
/**
* <p>
* 删除(根据ID 批量删除)
* </p>
*
* @param idList 主键ID列表
* @return boolean
*/
boolean deleteBatchIds(Collection<? extends Serializable> idList);
}
改
单改updateById
public interface BaseMapper<T> {
/**
* <p>
* 根据 ID 修改
* </p>
*
* @param entity 实体对象
* @return int
*/
Integer updateById(@Param("et") T entity);
}
条件改
public interface BaseMapper<T> {
/**
* <p>
* 根据 whereEntity 条件,更新记录
* </p>
*
* @param entity 实体对象
* @param wrapper 实体对象封装操作类(可以为 null)
* @return
*/
Integer update(@Param("et") T entity, @Param("ew") Wrapper<T> wrapper);
}
批量改
BaseMapper
只有单条修改,在IService
里有批量删除接口叫updateBatchById
public interface IService<T> {
/**
* <p>
* 根据ID 批量更新
* </p>
*
* @param entityList 实体对象列表
* @return boolean
*/
boolean updateBatchById(List<T> entityList);
}
查
单查
/**
* <p>
* 根据 ID 查询
* </p>
*
* @param id 主键ID
* @return T
*/
T selectById(Serializable id);
/**
* <p>
* 根据 entity 条件,查询一条记录
* </p>
*
* @param entity 实体对象
* @return T
*/
T selectOne(@Param("ew") T entity);
条件查
public interface BaseMapper<T> {
/**
* <p>
* 根据 entity 条件,查询全部记录
* </p>
*
* @param wrapper 实体对象封装操作类(可以为 null)
* @return List<T>
*/
List<T> selectList(@Param("ew") Wrapper<T> wrapper);
}
批量查
public interface IService<T> {
/**
* <p>
* 查询(根据ID 批量查询)
* </p>
*
* @param idList 主键ID列表
* @return List<T>
*/
List<T> selectBatchIds(Collection<? extends Serializable> idList);
}
单表:补充计数方法
Plus计数可以不用分组
@Override
public MsgTaskListResponse getTaskCountsGroupByMsgType(){
MsgTaskListResponse msgTaskListResponse = new MsgTaskListResponse();
//平台消息计数
Integer msgTaskPlatformCounts = msgTaskMapper.selectCount(new EntityWrapper<MsgTask>().eq(MsgTask.CONST_MSG_TYPE, MsgTask.CONST_MSGTYPE_PLATFORM));
msgTaskListResponse.setPlatformCounts(msgTaskPlatformCounts);
//企业消息计数
Integer msgTaskEntCounts = msgTaskMapper.selectCount(new EntityWrapper<MsgTask>().eq(MsgTask.CONST_MSG_TYPE, MsgTask.CONST_MSGTYPE_ENT));
msgTaskListResponse.setEntCounts(msgTaskEntCounts);
// 所有消息计数
Integer sumCounts = msgTaskMapper.selectCount(new EntityWrapper<>());
msgTaskListResponse.setSumCounts(sumCounts);
return msgTaskListResponse;
}
单表:条件构造器Wrapper
情况说明:<mybatisplus-starter.version>2.1.9</mybatisplus-starter.version>
Wrapper
是EntityWrapper
的父类- 用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
- 注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
```java
/**
- Copyright (c) 2011-2014, hubin (jobob@qq.com).
- 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.mapper;
import com.baomidou.mybatisplus.toolkit.StringUtils;
/**
- Entity 对象封装操作类,定义T-SQL语法
- *
- @author hubin , yanghu , Dyang , Caratacus
@Date 2016-11-7 */ @SuppressWarnings(“serial”) public class EntityWrapper
extends Wrapper { /**
数据库表映射实体类 */ protected T entity = null;
public EntityWrapper() { / 注意,传入查询参数 / }
public EntityWrapper(T entity) { this.entity = entity; }
public EntityWrapper(T entity, String sqlSelect) { this.entity = entity; this.sqlSelect = sqlSelect; }
@Override public T getEntity() { return entity; }
public void setEntity(T entity) { this.entity = entity; }
/**
SQL 片段 / @Override public String getSqlSegment() { /
无条件 */ String sqlWhere = sql.toString(); if (StringUtils.isEmpty(sqlWhere)) { return null; }
/*
- 根据当前实体判断是否需要将WHERE替换成 AND 增加实体不为空但所有属性为空的情况 */ return isWhere != null ? (isWhere ? sqlWhere : sqlWhere.replaceFirst(“WHERE”, AND_OR)) : sqlWhere.replaceFirst(“WHERE”, AND_OR); }
}
使用示例:
```java
Date date = new Date();
List<MsgTask> msgTasks = msgTaskMapper.selectList(new EntityWrapper<MsgTask>().lt(MsgTask.CONST_SEND_TIME,date).eq(MsgLog.CONST_SEND_STATE,MsgLog.SEND_STATUS_FAILED));
使用示例:if-test
Wrapper的第一个入参boolean condition
表示该条件是否加入最后生成的sql中,类似于Mybatis
XML的if-test
标签,例如:
@Override
public List<MsgLogConditionResponse> msgLogs(MsgLogConditionRequest msgLogConditionRequest) {
Page<MsgLog> page = new Page<>();
if (msgLogConditionRequest.getSize() != null) {
page.setSize(msgLogConditionRequest.getSize());
}
if (msgLogConditionRequest.getCurrent() != null) {
page.setCurrent(msgLogConditionRequest.getCurrent());
}
Boolean unRead = msgLogConditionRequest.getUnRead();
String sceneType = msgLogConditionRequest.getSceneType();
//分页列表SQL,if-test控制是否执行过滤
Page<MsgLog> pageResult = selectPage(page, new EntityWrapper<MsgLog>()
.eq(unRead, MsgLog.CONST_MSG_STATE, MsgLog.HAVED_NO_READ)
.eq(StringUtils.isNotBlank(sceneType), MsgLog.CONST_SCENE_TYPE, sceneType));
List<MsgLog> msgLogs = pageResult.getRecords();
ArrayList<MsgLogConditionResponse> responses = new ArrayList<>();
for (MsgLog msgLog : msgLogs) {
MsgLogConditionResponse msgLogConditionResponse = new MsgLogConditionResponse();
msgLogConditionResponse.setMsgContent(msgLog.getMsgContent());
msgLogConditionResponse.setReceiveTime(msgLog.getReceiveTime());
msgLogConditionResponse.setSceneType(msgLog.getSceneType());
msgLogConditionResponse.setMsgStatus(msgLog.getMsgState());
responses.add(msgLogConditionResponse);
}
return responses;
}
警告:
- wrapper 很重,不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输
- 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
- 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
- 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr
#allEq
allEq(Map<R, V> params)
allEq(Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
- 全部eq(或个别isNull)个别参数说明:
params
:key
为数据库字段名,value
为字段值null2IsNull
: 为true
则在map
的value
为null
时调用 isNull 方法,为false
时则忽略value
为null
的 - 例1:
allEq({id:1,name:"老王",age:null})
—->id = 1 and name = '老王' and age is null
- 例2:
allEq({id:1,name:"老王",age:null}, false)
—->id = 1 and name = '老王'
allEq(BiPredicate<R, V> filter, Map<R, V> params)
allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
个别参数说明:filter
: 过滤函数,是否允许字段传入比对条件中params
与 null2IsNull
: 同上
- 例1:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null})
—->name = '老王' and age is null
- 例2:
allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null}, false)
—->name = '老王'
#eq
eq(R column, Object val)
eq(boolean condition, R column, Object val)
- 等于 =
- 例:
eq("name", "老王")
—->name = '老王'
#ne
ne(R column, Object val)
ne(boolean condition, R column, Object val)
- 不等于 <>
- 例:
ne("name", "老王")
—->name <> '老王'
#gt
gt(R column, Object val)
gt(boolean condition, R column, Object val)
- 大于 >
- 例:
gt("age", 18)
—->age > 18
#ge
ge(R column, Object val)
ge(boolean condition, R column, Object val)
- 大于等于 >=
- 例:
ge("age", 18)
—->age >= 18
#lt
lt(R column, Object val)
lt(boolean condition, R column, Object val)
- 小于 <
- 例:
lt("age", 18)
—->age < 18
#le
le(R column, Object val)
le(boolean condition, R column, Object val)
- 小于等于 <=
- 例:
le("age", 18)
—->age <= 18
#between
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
- BETWEEN 值1 AND 值2
- 例:
between("age", 18, 30)
—->age between 18 and 30
#notBetween
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
- NOT BETWEEN 值1 AND 值2
- 例:
notBetween("age", 18, 30)
—->age not between 18 and 30
#like
like(R column, Object val)
like(boolean condition, R column, Object val)
- LIKE ‘%值%’
- 例:
like("name", "王")
—->name like '%王%'
#notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
- NOT LIKE ‘%值%’
- 例:
notLike("name", "王")
—->name not like '%王%'
#likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
- LIKE ‘%值’
- 例:
likeLeft("name", "王")
—->name like '%王'
#likeRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
- LIKE ‘值%’
- 例:
likeRight("name", "王")
—->name like '王%'
#isNull
isNull(R column)
isNull(boolean condition, R column)
- 字段 IS NULL
- 例:
isNull("name")
—->name is null
#isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)
- 字段 IS NOT NULL
- 例:
isNotNull("name")
—->name is not null
#in
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
- 字段 IN (value.get(0), value.get(1), …)
- 例:
in("age",{1,2,3})
—->age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)
- 字段 IN (v0, v1, …)
- 例:
in("age", 1, 2, 3)
—->age in (1,2,3)
#notIn
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
- 字段 NOT IN (value.get(0), value.get(1), …)
- 例:
notIn("age",{1,2,3})
—->age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
- 字段 NOT IN (v0, v1, …)
- 例:
notIn("age", 1, 2, 3)
—->age not in (1,2,3)
#inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
- 字段 IN ( sql语句 )
- 例:
inSql("age", "1,2,3,4,5,6")
—->age in (1,2,3,4,5,6)
- 例:
inSql("id", "select id from table where id < 3")
—->id in (select id from table where id < 3)
#notInSql
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
- 字段 NOT IN ( sql语句 )
- 例:
notInSql("age", "1,2,3,4,5,6")
—->age not in (1,2,3,4,5,6)
- 例:
notInSql("id", "select id from table where id < 3")
—->id not in (select id from table where id < 3)
#groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)
- 分组:GROUP BY 字段, …
- 例:
groupBy("id", "name")
—->group by id,name
与SQL分组同理:满足“SELECT子句中的列名必须为分组列或列函数”
@Override
public MsgTaskSendLogConditionResponse getSendDetailGroup(MsgTaskSendLogConditionRequest msgTaskSendLogConditionRequest) {
MsgTaskSendLogConditionResponse msgTaskSendLogConditionResponse = new MsgTaskSendLogConditionResponse();
Integer msgTaskId = msgTaskSendLogConditionRequest.getMsgTaskId();
//查询
Page page = new Page<>((msgTaskSendLogConditionRequest.getCurrent() == null ? 1 : msgTaskSendLogConditionRequest.getCurrent()), (msgTaskSendLogConditionRequest.getSize() == null ? 10 : msgTaskSendLogConditionRequest.getSize()));
msgTaskMapper.getSendDetailPage(page, msgTaskSendLogConditionRequest);
msgTaskSendLogConditionResponse.setCountsOfSended(page.getTotal());
//logs表单表,countsOfSuccess;分组
List<MsgLog> msgLogSuccess = msgLogMapper.selectList(new EntityWrapper<MsgLog>().setSqlSelect(MsgLog.CONST_SEND_STATE + ",count(*) AS counts_of_success")
.eq(MsgLog.CONST_SEND_STATE, MsgLog.SEND_STATUS_SUCCESS)
.eq(MsgLog.CONST_STATUS, MsgLog.DELETE_STATUS_VALIDATED)
.groupBy(MsgLog.CONST_SEND_STATE));
msgTaskSendLogConditionResponse.setCountsOfSuccess(msgLogSuccess.size() == 0 ? 0 : msgLogSuccess.get(0).getCountsOfSuccess());
//logs表单表,countsOfFailed;分组
List<MsgLog> msgLogFailed = msgLogMapper.selectList(new EntityWrapper<MsgLog>().setSqlSelect(MsgLog.CONST_SEND_STATE + ",count(*) AS counts_of_failed")
.eq(MsgLog.CONST_SEND_STATE, MsgLog.SEND_STATUS_FAILED)
.eq(MsgLog.CONST_STATUS, MsgLog.DELETE_STATUS_VALIDATED)
.groupBy(MsgLog.CONST_SEND_STATE));
msgTaskSendLogConditionResponse.setCountsOfFailed(msgLogFailed.size() == 0 ? 0 : msgLogFailed.get(0).getCountsOfFailed());
//logs表单表,countsOfReaded;分组
List<MsgLog> msgLogReaded = msgLogMapper.selectList(new EntityWrapper<MsgLog>().setSqlSelect(MsgLog.CONST_SEND_STATE + ",count(*) AS counts_of_readed")
.eq(MsgLog.CONST_MSG_STATE, MsgLog.HAVED_READ)
.eq(MsgLog.CONST_STATUS, MsgLog.DELETE_STATUS_VALIDATED)
.groupBy(MsgLog.CONST_SEND_STATE));
msgTaskSendLogConditionResponse.setCountsOfReaded(msgLogReaded.size() == 0 ? 0 : msgLogReaded.get(0).getCountsOfReaded());
return msgTaskSendLogConditionResponse;
}
其中setSqlSelect
的SQL里的counts_of_success
和counts_of_failed
和counts_of_readed
:注意是下划线
//logs表单表,countsOfSuccess;分组
List<MsgLog> msgLogSuccess = msgLogMapper.selectList(new EntityWrapper<MsgLog>().setSqlSelect(MsgLog.CONST_SEND_STATE + ",count(*) AS counts_of_success")
.eq(MsgLog.CONST_SEND_STATE, MsgLog.SEND_STATUS_SUCCESS)
.eq(MsgLog.CONST_STATUS, MsgLog.DELETE_STATUS_VALIDATED)
.groupBy(MsgLog.CONST_SEND_STATE));
msgTaskSendLogConditionResponse.setCountsOfSuccess(msgLogSuccess.size() == 0 ? 0 : msgLogSuccess.get(0).getCountsOfSuccess());
需要在Entity
配置额外的统计字段counts_of_success
,counts_of_failed
,counts_of_readed
@TableField(exist = false)
private static final long serialVersionUID = 1L;
@TableField(exist = false)
public Integer countsOfSuccess;
@TableField(exist = false)
public Integer countsOfFailed;
@TableField(exist = false)
public Integer countsOfReaded;
#orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
- 排序:ORDER BY 字段, … ASC
- 例:
orderByAsc("id", "name")
—->order by id ASC,name ASC
#orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
- 排序:ORDER BY 字段, … DESC
例:
orderByDesc("id", "name")
—->order by id DESC,name DESC
#orderBy
orderBy(boolean condition, boolean isAsc, R... columns)
排序:ORDER BY 字段, …
- 例:
orderBy(true, true, "id", "name")
—->order by id ASC,name ASC
#having
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
- HAVING ( sql语句 )
- 例:
having("sum(age) > 10")
—->having sum(age) > 10
- 例:
having("sum(age) > {0}", 11)
—->having sum(age) > 11
#func
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
- func 方法(主要方便在出现if…else下调用不同方法能不断链)
- 例:
func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})
#or
or()
or(boolean condition)
- 拼接 OR注意事项:
主动调用or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接) - 例:
eq("id",1).or().eq("name","老王")
—->id = 1 or name = '老王'
or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
- OR 嵌套
- 例:
or(i -> i.eq("name", "李白").ne("status", "活着"))
—->or (name = '李白' and status <> '活着')
#and
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
- AND 嵌套
- 例:
and(i -> i.eq("name", "李白").ne("status", "活着"))
—->and (name = '李白' and status <> '活着')
#nested
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
- 正常嵌套 不带 AND 或者 OR
- 例:
nested(i -> i.eq("name", "李白").ne("status", "活着"))
—->(name = '李白' and status <> '活着')
#apply
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
- 拼接 sql注意事项:
该方法可用于数据库函数 动态入参的params
对应前面applySql
内部的{index}
部分.这样是不会有sql注入风险的,反之会有! - 例:
apply("id = 1")
—->id = 1
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
—->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
- 例:
apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")
—->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
#last
last(String lastSql)
last(boolean condition, String lastSql)
- 无视优化规则直接拼接到 sql 的最后
- 注意事项:只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
- 例:
last("limit 1")
#exists
exists(String existsSql)
exists(boolean condition, String existsSql)
- 拼接 EXISTS ( sql语句 )
- 例:
exists("select id from table where age = 1")
—->exists (select id from table where age = 1)
#notExists
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
- 拼接 NOT EXISTS ( sql语句 )
- 例:
notExists("select id from table where age = 1")
—->not exists (select id from table where age = 1)