mybatis plus查询条件拼接

只是为了收藏 原帖写得很好 直接点链接过去吧

原帖连接呢~

mybatis plus条件拼接

条件构造器

说明:

  • 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中
  • 没有标明condition的方法,默认为true
  • 以下出现的泛型Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法)
  • 以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段idgetMethod)
  • 参数R column均表示数据库字段,而不是实体类数据字段名!!!(字段名是数据库关键字的自己用转义符包裹!)!
  • 以下举例均为使用普通wrapper,入参为MapList的均以json形式表现!
  • 使用中如果入参的Map或者List,则不会加入最后生成的sql中!!!
  • 有任何疑问就点开源码看,看不懂函数的点击我学习新知识

警告:
不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输(远程调用)

  1. wrapper 很重
  2. 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
  3. 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
  4. 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr

案例table

 
    
  1. CREATE TABLE `aaa_bbb_cc` (
  2. `ID` int(10) NOT NULL AUTO_INCREMENT,
  3. `aa_as` varchar(255) DEFAULT NULL,
  4. `ab_AAA` varchar(255) DEFAULT NULL,
  5. PRIMARY KEY (`ID`)
  6. ) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
 
    
  1. @Data
  2. @AllArgsConstructor
  3. @NoArgsConstructor
  4. public class AaaBbbCc implements Serializable {
  5. private static final long serialVersionUID = 1L;
  6. @TableId(value = "ID", type = IdType.AUTO)
  7. private Integer id;
  8. private String aaAs;
  9. @TableField("ab_AAA")
  10. private String abAaa;
  11. }

AbstractWrapper

说明:
QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

allEq:全部eq(或个别isNull)

 
    
  1. allEq(Map params)
  2. allEq(Map params, boolean null2IsNull)
  3. allEq(boolean condition, Map params, boolean null2IsNull)
  4. allEq(BiPredicate filter, Map params)
  5. allEq(BiPredicate filter, Map params, boolean null2IsNull)
  6. allEq(boolean condition, BiPredicate filter, Map params, boolean null2IsNull)
  • 参数说明:
    params : key数据库字段名(注意不是entity),value为字段值
    null2IsNull : 为true则在mapvaluenull时调用 isNull 方法,为false时则忽略valuenull
    filter : 过滤函数,是否允许字段传入比对条件中

  • 案例

 
    
  1. Map stringTMap=new LinkedHashMap<>();
  2. stringTMap.put("ID",12 );
  3. stringTMap.put("aa_as",null);
  4. queryWrapper.allEq(stringTMap);//ID = ? AND aa_as IS NULL :null的直接is null
  5. queryWrapper.allEq(stringTMap,false);// WHERE ID = ? :null的不查询
  6. queryWrapper.allEq(false,stringTMap,false);// condition为false,不拼接此查询条件
  7. //x是字段,y是对应的值,使用Lambda表达式进行条件的校验
  8. BiPredicate bi = (x, y) -> x .equals("ID");
  9. queryWrapper.allEq(bi,stringTMap);//WHERE ID = ?

eq:等于 =

 
    
  1. eq(R column, Object val)
  2. eq(boolean condition, R column, Object val)
  • 例: eq("name", "老王")--->name = '老王'

ne:不等于 <>

 
    
  1. ne(R column, Object val)
  2. ne(boolean condition, R column, Object val)
  • 例: ne("name", "老王")--->name <> '老王'

gt:大于 >

 
    
  1. gt(R column, Object val)
  2. gt(boolean condition, R column, Object val)
  • 例: gt("age", 18)--->age > 18

ge:大于等于 >=

 
    
  1. ge(R column, Object val)
  2. ge(boolean condition, R column, Object val)
  • 例: ge("age", 18)--->age >= 18

lt:小于 <

 
    
  1. lt(R column, Object val)
  2. lt(boolean condition, R column, Object val)
  • 例: lt("age", 18)--->age < 18

le:小于等于 <=

 
    
  1. le(R column, Object val)
  2. le(boolean condition, R column, Object val)
  • 例: le("age", 18)--->age <= 18

between:BETWEEN 值1 AND 值2

 
    
  1. between(R column, Object val1, Object val2)
  2. between(boolean condition, R column, Object val1, Object val2)
  • 例: between("age", 18, 30)--->age between 18 and 30

notBetween:NOT BETWEEN 值1 AND 值2

 
    
  1. notBetween(R column, Object val1, Object val2)
  2. notBetween(boolean condition, R column, Object val1, Object val2)
  • 例: notBetween("age", 18, 30)--->age not between 18 and 30

like:LIKE '%值%'

 
    
  1. like(R column, Object val)
  2. like(boolean condition, R column, Object val)
  • 例: like("name", "王")--->name like '%王%'

notLike:NOT LIKE '%值%'

 
    
  1. notLike(R column, Object val)
  2. notLike(boolean condition, R column, Object val)
  • 例: notLike("name", "王")--->name not like '%王%'

likeLeft:LIKE '%值'

 
    
  1. likeLeft(R column, Object val)
  2. likeLeft(boolean condition, R column, Object val)
  • 例: likeLeft("name", "王")--->name like '%王'

likeRight:LIKE '值%'

 
    
  1. likeRight(R column, Object val)
  2. likeRight(boolean condition, R column, Object val)
  • 例: likeRight("name", "王")--->name like '王%'

isNull:字段 IS NULL

 
    
  1. isNull(R column)
  2. isNull(boolean condition, R column)
  • 例: isNull("name")--->name is null

isNotNull: 字段 IS NULL

 
    
  1. isNotNull(R column)
  2. isNotNull(boolean condition, R column)
  • 例: isNotNull("name")--->name is not null

in:字段 IN

 
    
  1. in(R column, Collection value)
  2. in(boolean condition, R column, Collection value)
  • 字段 IN (value.get(0), value.get(1), ...)
  • 例: in("age",{1,2,3})--->age in (1,2,3)
 
    
  1. in(R column, Object... values)
  2. in(boolean condition, R column, Object... values)
  • 字段 IN (v0, v1, ...)
  • 例: in("age", 1, 2, 3)--->age in (1,2,3)

notIn:字段 NOT IN

 
    
  1. notIn(R column, Collection value)
  2. notIn(boolean condition, R column, Collection value)
  • 字段 IN (value.get(0), value.get(1), ...)
  • 例: notIn("age",{1,2,3})--->age not in (1,2,3)
 
    
  1. notIn(R column, Object... values)
  2. notIn(boolean condition, R column, Object... values)
  • 字段 NOT IN (v0, v1, ...)
  • 例: notIn("age", 1, 2, 3)--->age not in (1,2,3)

inSql:字段 IN ( sql语句 )

 
    
  1. inSql(R column, String inValue)
  2. 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:字段 NOT IN ( sql语句 )

 
    
  1. notInSql(R column, String inValue)
  2. 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:分组:GROUP BY 字段, ...

 
    
  1. groupBy(R... columns)
  2. groupBy(boolean condition, R... columns)
  • 例: groupBy("id", "name")--->group by id,name

orderByAsc:排序:ORDER BY 字段, ... ASC

 
    
  1. orderByAsc(R... columns)
  2. orderByAsc(boolean condition, R... columns)
  • 例: orderByAsc("id", "name")--->order by id ASC,name ASC

orderByDesc 排序:ORDER BY 字段, ... DESC

 
    
  1. orderByDesc(R... columns)
  2. orderByDesc(boolean condition, R... columns)
  • 例: orderByDesc("id", "name")--->order by id DESC,name DESC

orderBy:排序:ORDER BY 字段, ...

 
    
  1. orderBy(boolean condition, boolean isAsc, R... columns)
  • 排序:ORDER BY 字段, ...
  • 例: orderBy(true, true, "id", "name")--->order by id ASC,name ASC
 
    
  1. queryWrapper.orderByAsc("aa_as");
  2. queryWrapper.orderByDesc("ab_AAA");
  3. //ORDER BY aa_as ASC , ab_AAA DESC

having:HAVING ( sql语句 )

 
    
  1. having(String sqlHaving, Object... params)
  2. 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

 
    
  1. or()
  2. or(boolean condition)

注意事项:
主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接)

  • 例: eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'
 
    
  1. or(Function func)
  2. or(boolean condition, Function func)
  • OR 嵌套
  • 例: or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着')
 
    
  1. queryWrapper.eq("ID" ,13 );
  2. queryWrapper.or();
  3. queryWrapper.eq("ID" ,14);
  4. queryWrapper.ne("aa_as","rtget" );
  5. //ID = ? OR (ID = ? AND aa_as <> ?)
  6. queryWrapper.eq("ID" ,13 ).or(i->i.eq("ID" ,14 ).ne("aa_as","rtget" )).or(i->i.eq("aa_as","测试2" ))//要在一条上才能连上 or(Function func)
  7. //WHERE ID = ? OR ( ID = ? AND aa_as <> ? ) OR ( aa_as = ? )

and:AND 嵌套

 
    
  1. and(Function func)
  2. and(boolean condition, Function func)
  • 例: and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着')

nested:正常嵌套 不带 AND 或者 OR

 
    
  1. nested(Function func)
  2. nested(boolean condition, Function func)
  • 例: nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')

apply:拼接 sql

 
    
  1. apply(String applySql, Object... params)
  2. 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:无视优化规则直接拼接到 sql 的最后

 
    
  1. last(String lastSql)
  2. last(boolean condition, String lastSql)

注意事项:
只能调用一次,多次调用以最后一次为准
有sql注入的风险,请谨慎使用

  • 例: last("limit 1")

exists:拼接 EXISTS ( sql语句 )

 
    
  1. exists(String existsSql)
  2. exists(boolean condition, String existsSql)
  • 例: exists("select id from table where age = 1")--->exists (select id from table where age = 1)

notExists:拼接 NOT EXISTS ( sql语句 )

 
    
  1. notExists(String notExistsSql)
  2. notExists(boolean condition, String notExistsSql)
  • 例: notExists("select id from table where age = 1")--->not exists (select id from table where age = 1)

QueryWrapper(select)

说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取

select:设置查询字段

 
    
  1. select(String... sqlSelect)
  2. select(Predicate predicate)
  3. select(Class entityClass, Predicate predicate)

说明:
以上方分法为两类.
第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值!
这两类方法重复调用以最后一次为准

  • 例: select("id", "name", "age")
  • 例: select(i -> i.getProperty().startsWith("test"))

excludeColumns:排除查询字段

已从3.0.5版本上移除此方法!

UpdateWrapper(update)

说明:
继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
及 LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取!

set

 
    
  1. set(String column, Object val)
  2. set(boolean condition, String column, Object val)
  • SQL SET 字段
  • 例: set("name", "老李头")
  • 例: set("name", "")--->数据库字段值变为空字符串
  • 例: set("name", null)--->数据库字段值变为null

setSql:设置 SET 部分 SQL

 
    
  1. setSql(String sql)
  • 例: set("name = '老李头')

lambda

  • 获取 LambdaWrapper
    QueryWrapper中是获取LambdaQueryWrapper
    UpdateWrapper中是获取LambdaUpdateWrapper

使用 Wrapper 自定义SQL

需求来源:
在使用了mybatis-plus之后, 自定义SQL的同时也想使用Wrapper的便利应该怎么办?
mybatis-plus版本3.0.7得到了完美解决
版本需要大于或等于3.0.7, 以下两种方案取其一即可

Service.java

 
    
  1. mysqlMapper.getAll(Wrappers.lambdaQuery().eq(MysqlData::getGroup, 1));

方案一 注解方式 Mapper.java

 
    
  1. @Select("select * from mysql_data ${ew.customSqlSegment}")
  2. List getAll(@Param(Constants.WRAPPER) Wrapper wrapper);

方案二 XML形式 Mapper.xml

 
    
  1. SELECT * FROM mysql_data ${ew.customSqlSegment}

分页查询

mybatis plus提供了分页功能,可以轻松实现分页;

 
    
  1. //设置查询参数
  2. Page page=new Page<>();
  3. page.setCurrent(1);
  4. page.setSize(2);
  5. //开始查询
  6. IPage page2 = aaaBbbCcDao.page(page);
  7. /**
  8. getCurrent():当前页数;
  9. getPages():总页数;
  10. getSize():查询数量;
  11. getTotal():总数量;
  12. getRecords():查询结果;
  13. 若是当前页>总页数,返回[];
  14. 若是当前页数<1,查询第一页数据;
  15. */

自定义SQL查询分页数据

  • Page page 参数设置为查询的第一个参数,不需要拼接分页查询条件,mybatis plus会自动执行分页查询;
  • 例:
 
    
  1. /**
  2. *

  3. * 查询 : 根据state状态查询用户列表,分页显示
  4. * 注意!!: 如果入参是有多个,需要加注解指定参数名才能在xml中取值
  5. *

  6. *
  7. * @param page 分页对象,xml中可以从里面进行取值,传递参数 Page 即自动分页,必须放在第一位(你可以继承Page实现自己的分页对象)
  8. * @param state 状态
  9. * @return 分页对象
  10. */
  11. @Select("SELECT id,name FROM user WHERE state=#{state}")
  12. IPage selectPageVo(Page page, @Param("state") Integer state);

热部署(已过时)

在3.1.0已经完全移除了....我们用的是3.1.1,用不了了o(╥﹏╥)o

逻辑删除(不建议使用)

在正式项目中,删除数据时很多时候不是将数据直接删除,而是创建一个字段,用不同的数据表示不同的状态;
比如创建一个enable字段,enable=1,则表示数据使用中,enable=0,则表示数据逻辑上已经删除了,平时使用时,这条数据默认不查询;
在mybatis plus中可以设置逻辑删除的查询;

配置

  • yml
 
    
  1. mybatis-plus:
  2. global-config:
  3. db-config:
  4. logic-delete-value: 0 # 逻辑已删除值(默认为 1)
  5. logic-not-delete-value: 1 # 逻辑未删除值(默认为 0)
  • entity
 
    
  1. //在代表删除的字段上添加注解:
  2. @TableLogic
  3. private Integer enable;

使用

 
    
  1. //默认在查询的时候就会拼接上enable的条件
  2. dao.list();//where enable=1

注意,此查询条件不会被覆盖,使用功能需谨慎

 
    
  1. //若是想要查询已经删除的数据,将无法查询....
  2. queryWrapper.eq("enable","0" );
  3. dao.list(queryWrapper);//WHERE enable=1 AND enable = 0

所以还是自己写吧o(╥﹏╥)o

枚举

自3.1.0开始,可配置默认枚举处理类来省略扫描通用枚举配置,3.1.0之前和之后的配置是不同的,我们就不研究3.1.0之前的使用方法了(#^.^#)

配置

  • 扫描通用枚举
 
    
  1. mybatis-plus:
  2. # 支持统配符 * 或者 ; 分割
  3. typeEnumsPackage: com.baomidou.springboot.entity.enums,自定义枚举
  • entity配置/JSON序列化处理
    • Jackson
 
    
  1. 在需要响应描述字段的get方法上添加@JsonValue注解即可
  • Fastjson
    • 全局处理方式
      ```java
      FastJsonConfig config = new FastJsonConfig();
      //设置WriteEnumUsingToString
      config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString);
      converter.setFastJsonConfig(config);
 
    
  1. - 局部处理方式
  2. ```java
  3. @JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
  4. private UserStatus status;

实现 IEnum 接口

  • 例:年龄使用枚举
    • 创建枚举

       
              
      1. @AllArgsConstructor
      2. public enum AgeEnum implements IEnum {
      3. ONE(1, "一岁"),
      4. TWO(2, "二岁"),
      5. THREE(3, "三岁");
      6. private int value;
      7. private String desc;
      8. @Override
      9. public Integer getValue() {
      10. return this.value;
      11. }
      12. public String geDesc() {
      13. return this.desc;
      14. }
      15. }
    • entity中设置枚举

       
              
      1. public class User{
      2. /**
      3. * 名字
      4. * 数据库字段: name varchar(20)
      5. */
      6. private String name;
      7. /**
      8. * 年龄,IEnum接口的枚举处理
      9. * 数据库字段:age INT(3)
      10. */
      11. private AgeEnum age;
      12. }

使用

数据库中数据为":张三",3
json转换后为:"张三","THREE"

注意:age在set的时候需要设置枚举而不是之前的Integer了,但是用户可以自己设置set方法,将传入的Integer转为枚举再赋值....

你可能感兴趣的:(mybatis,mybatis,java,数据库)