只是为了收藏 原帖写得很好 直接点链接过去吧
原帖连接呢~
说明
:
- 以下出现的第一个入参
boolean condition
表示该条件是否加入最后生成的sql中- 没有标明
condition
的方法,默认为true
- 以下出现的泛型
Param
均为Wrapper
的子类实例(均具有AbstractWrapper
的所有方法)- 以下方法在入参中出现的
R
为泛型,在普通wrapper中是String
,在LambdaWrapper中是函数(例:Entity::getId
,Entity
为实体类,getId
为字段id
的getMethod)- 参数
R column
均表示数据库字段
,而不是实体类数据字段名!!!(字段名是数据库关键字的自己用转义符包裹!)!- 以下举例均为使用普通wrapper,入参为
Map
和List
的均以json
形式表现!- 使用中如果入参的
Map
或者List
为空,则不会加入最后生成的sql中!!!- 有任何疑问就点开源码看,看不懂函数的点击我学习新知识
警告
:
不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输(远程调用)
- wrapper 很重
- 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
- 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
- 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr
CREATE TABLE `aaa_bbb_cc` (
`ID` int(10) NOT NULL AUTO_INCREMENT,
`aa_as` varchar(255) DEFAULT NULL,
`ab_AAA` varchar(255) DEFAULT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AaaBbbCc implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "ID", type = IdType.AUTO)
private Integer id;
private String aaAs;
@TableField("ab_AAA")
private String abAaa;
}
说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为
allEq(Map params)
allEq(Map params, boolean null2IsNull)
allEq(boolean condition, Map params, boolean null2IsNull)
allEq(BiPredicate filter, Map params)
allEq(BiPredicate filter, Map params, boolean null2IsNull)
allEq(boolean condition, BiPredicate filter, Map params, boolean null2IsNull)
参数说明:params
: key
为数据库字段名(注意不是entity),value
为字段值null2IsNull
: 为true
则在map
的value
为null
时调用 isNull 方法,为false
时则忽略value
为null
的filter
: 过滤函数,是否允许字段传入比对条件中
案例
Map stringTMap=new LinkedHashMap<>();
stringTMap.put("ID",12 );
stringTMap.put("aa_as",null);
queryWrapper.allEq(stringTMap);//ID = ? AND aa_as IS NULL :null的直接is null
queryWrapper.allEq(stringTMap,false);// WHERE ID = ? :null的不查询
queryWrapper.allEq(false,stringTMap,false);// condition为false,不拼接此查询条件
//x是字段,y是对应的值,使用Lambda表达式进行条件的校验
BiPredicate bi = (x, y) -> x .equals("ID");
queryWrapper.allEq(bi,stringTMap);//WHERE ID = ?
eq(R column, Object val)
eq(boolean condition, R column, Object val)
eq("name", "老王")
--->name = '老王'
ne(R column, Object val)
ne(boolean condition, R column, Object val)
ne("name", "老王")
--->name <> '老王'
gt(R column, Object val)
gt(boolean condition, R column, Object val)
gt("age", 18)
--->age > 18
ge(R column, Object val)
ge(boolean condition, R column, Object val)
ge("age", 18)
--->age >= 18
lt(R column, Object val)
lt(boolean condition, R column, Object val)
lt("age", 18)
--->age < 18
le(R column, Object val)
le(boolean condition, R column, Object val)
le("age", 18)
--->age <= 18
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
between("age", 18, 30)
--->age between 18 and 30
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
notBetween("age", 18, 30)
--->age not between 18 and 30
like(R column, Object val)
like(boolean condition, R column, Object val)
like("name", "王")
--->name like '%王%'
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
notLike("name", "王")
--->name not like '%王%'
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
likeLeft("name", "王")
--->name like '%王'
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
likeRight("name", "王")
--->name like '王%'
isNull(R column)
isNull(boolean condition, R column)
isNull("name")
--->name is null
isNotNull(R column)
isNotNull(boolean condition, R column)
isNotNull("name")
--->name is not null
in(R column, Collection> value)
in(boolean condition, R column, Collection> value)
in("age",{1,2,3})
--->age in (1,2,3)
in(R column, Object... values)
in(boolean condition, R column, Object... values)
in("age", 1, 2, 3)
--->age in (1,2,3)
notIn(R column, Collection> value)
notIn(boolean condition, R column, Collection> value)
notIn("age",{1,2,3})
--->age not in (1,2,3)
notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
notIn("age", 1, 2, 3)
--->age not in (1,2,3)
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
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(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
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")
--->age not in (select id from table where id < 3)
groupBy(R... columns)
groupBy(boolean condition, R... columns)
groupBy("id", "name")
--->group by id,name
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
orderByAsc("id", "name")
--->order by id ASC,name ASC
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
orderByDesc("id", "name")
--->order by id DESC,name DESC
orderBy(boolean condition, boolean isAsc, R... columns)
orderBy(true, true, "id", "name")
--->order by id ASC,name ASC
queryWrapper.orderByAsc("aa_as");
queryWrapper.orderByDesc("ab_AAA");
//ORDER BY aa_as ASC , ab_AAA DESC
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
having("sum(age) > 10")
--->having sum(age) > 10
having("sum(age) > {0}", 11)
--->having sum(age) > 11
or()
or(boolean condition)
注意事项:
主动调用or
表示紧接着下一个方法不是用and
连接!(不调用or
则默认为使用and
连接)
eq("id",1).or().eq("name","老王")
--->id = 1 or name = '老王'
or(Function func)
or(boolean condition, Function func)
or(i -> i.eq("name", "李白").ne("status", "活着"))
--->or (name = '李白' and status <> '活着')
queryWrapper.eq("ID" ,13 );
queryWrapper.or();
queryWrapper.eq("ID" ,14);
queryWrapper.ne("aa_as","rtget" );
//ID = ? OR (ID = ? AND aa_as <> ?)
queryWrapper.eq("ID" ,13 ).or(i->i.eq("ID" ,14 ).ne("aa_as","rtget" )).or(i->i.eq("aa_as","测试2" ))//要在一条上才能连上 or(Function func)
//WHERE ID = ? OR ( ID = ? AND aa_as <> ? ) OR ( aa_as = ? )
and(Function func)
and(boolean condition, Function func)
and(i -> i.eq("name", "李白").ne("status", "活着"))
--->and (name = '李白' and status <> '活着')
nested(Function func)
nested(boolean condition, Function func)
nested(i -> i.eq("name", "李白").ne("status", "活着"))
--->(name = '李白' and status <> '活着')
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
注意事项:
该方法可用于数据库函数
动态入参的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(String lastSql)
last(boolean condition, String lastSql)
注意事项:
只能调用一次,多次调用以最后一次为准
有sql注入的风险,请谨慎使用
last("limit 1")
exists(String existsSql)
exists(boolean condition, String existsSql)
exists("select id from table where age = 1")
--->exists (select id from table where age = 1)
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
notExists("select id from table where age = 1")
--->not exists (select id from table where age = 1)
说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取
select(String... sqlSelect)
select(Predicate predicate)
select(Class entityClass, Predicate predicate)
说明:
以上方分法为两类.
第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper
内的entity
属性有值!
这两类方法重复调用以最后一次为准
select("id", "name", "age")
select(i -> i.getProperty().startsWith("test"))
已从
3.0.5
版本上移除此方法!
说明:
继承自AbstractWrapper
,自身的内部属性entity
也用于生成 where 条件
及LambdaUpdateWrapper
, 可以通过new UpdateWrapper().lambda()
方法获取!
set(String column, Object val)
set(boolean condition, String column, Object val)
set("name", "老李头")
set("name", "")
--->数据库字段值变为空字符串set("name", null)
--->数据库字段值变为null
setSql(String sql)
set("name = '老李头')
LambdaWrapper
QueryWrapper
中是获取LambdaQueryWrapper
UpdateWrapper
中是获取LambdaUpdateWrapper
需求来源:
在使用了mybatis-plus
之后, 自定义SQL的同时也想使用Wrapper
的便利应该怎么办?
在mybatis-plus
版本3.0.7
得到了完美解决
版本需要大于或等于3.0.7
, 以下两种方案取其一即可
mysqlMapper.getAll(Wrappers.lambdaQuery().eq(MysqlData::getGroup, 1));
@Select("select * from mysql_data ${ew.customSqlSegment}")
List getAll(@Param(Constants.WRAPPER) Wrapper wrapper);
SELECT * FROM mysql_data ${ew.customSqlSegment}
mybatis plus提供了分页功能,可以轻松实现分页;
//设置查询参数
Page page=new Page<>();
page.setCurrent(1);
page.setSize(2);
//开始查询
IPage page2 = aaaBbbCcDao.page(page);
/**
getCurrent():当前页数;
getPages():总页数;
getSize():查询数量;
getTotal():总数量;
getRecords():查询结果;
若是当前页>总页数,返回[];
若是当前页数<1,查询第一页数据;
*/
Page page
参数设置为查询的第一个参数,不需要拼接分页查询条件,mybatis plus会自动执行分页查询;/**
*
* 查询 : 根据state状态查询用户列表,分页显示
* 注意!!: 如果入参是有多个,需要加注解指定参数名才能在xml中取值
*
*
* @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
* @param state 状态
* @return 分页对象
*/
@Select("SELECT id,name FROM user WHERE state=#{state}")
IPage selectPageVo(Page page, @Param("state") Integer state);
在3.1.0已经完全移除了....我们用的是3.1.1,用不了了o(╥﹏╥)o
在正式项目中,删除数据时很多时候不是将数据直接删除,而是创建一个字段,用不同的数据表示不同的状态;
比如创建一个enable
字段,enable=1
,则表示数据使用中,enable=0
,则表示数据逻辑上已经删除了,平时使用时,这条数据默认不查询;
在mybatis plus中可以设置逻辑删除的查询;
mybatis-plus:
global-config:
db-config:
logic-delete-value: 0 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 1 # 逻辑未删除值(默认为 0)
//在代表删除的字段上添加注解:
@TableLogic
private Integer enable;
//默认在查询的时候就会拼接上enable的条件
dao.list();//where enable=1
注意,此查询条件不会被覆盖,使用功能需谨慎
//若是想要查询已经删除的数据,将无法查询....
queryWrapper.eq("enable","0" );
dao.list(queryWrapper);//WHERE enable=1 AND enable = 0
所以还是自己写吧o(╥﹏╥)o
自3.1.0开始,可配置默认枚举处理类来省略扫描通用枚举配置,3.1.0之前和之后的配置是不同的,我们就不研究3.1.0之前的使用方法了(#^.^#)
mybatis-plus:
# 支持统配符 * 或者 ; 分割
typeEnumsPackage: com.baomidou.springboot.entity.enums,自定义枚举
在需要响应描述字段的get方法上添加@JsonValue注解即可
- 局部处理方式
```java
@JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
private UserStatus status;
创建枚举
@AllArgsConstructor
public enum AgeEnum implements IEnum {
ONE(1, "一岁"),
TWO(2, "二岁"),
THREE(3, "三岁");
private int value;
private String desc;
@Override
public Integer getValue() {
return this.value;
}
public String geDesc() {
return this.desc;
}
}
entity中设置枚举
public class User{
/**
* 名字
* 数据库字段: name varchar(20)
*/
private String name;
/**
* 年龄,IEnum接口的枚举处理
* 数据库字段:age INT(3)
*/
private AgeEnum age;
}
数据库中数据为":张三",3
json转换后为:"张三","THREE"
注意:age在set的时候需要设置枚举而不是之前的Integer了,但是用户可以自己设置set方法,将传入的Integer转为枚举再赋值....