在后台管理中 , 常常需要设置多个条件来筛选数据 , 也就是多条件查询
多条件查询
Spring Boot+Mybatis多条件模糊查询,动态sql_fanminghao的博客-CSDN博客
在此 SQL 语句中, where 1=1 是多条件拼接时的小技巧, 后面的条件查询就可以都用 and 了。
使用 if 标签来处理动态 SQL
注意if标签里面的 test , 对应的应该是实体类的属性名
实体类
User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| package com.miao.domain;
import com.baomidou.mybatisplus.annotation.*; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data;
import java.io.Serializable; import java.util.Date; import java.util.Objects;
@TableName(value ="t_user") @Data @ApiModel("用户表") public class User implements Serializable {
@TableId(type = IdType.AUTO) @ApiModelProperty(value = "用户id") private Integer userId;
@ApiModelProperty(value = "用户昵称") private String userName;
@ApiModelProperty(value = "账户名") private String userAccount;
@ApiModelProperty(value = "密码",hidden = true) private String userPassword;
@ApiModelProperty(value = "学校") private String school;
@ApiModelProperty(value = "头像url") private String avatarUrl;
@ApiModelProperty(value = "性别") private Integer gender;
@ApiModelProperty(value = "电话") private String phone;
@ApiModelProperty(value = "邮箱") private String email;
@ApiModelProperty(value = "注册时间") private Date createTime;
@ApiModelProperty(value = "生日") private Date birth;
@ApiModelProperty(value = "更新时间") private Date updateTime;
@ApiModelProperty(value = "权限") private int isAdmin;
@TableLogic @ApiModelProperty(value = "逻辑删除") private int isDelete;
@TableField(exist = false) private static final long serialVersionUID = 1L;
}
|
UserSelectiveDTO.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.miao.DTO;
import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.bind.DefaultValue; import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
@Data @ApiModel("多条件查询用户实体类") public class UserSelectiveDTO {
@ApiModelProperty(name = "用户名称" ) private String userName;
@ApiModelProperty(name = "用户性别" ) private Integer gender;
@ApiModelProperty(name = "学校" ) private String school;
@ApiModelProperty(name = "创建时间" ) @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss") @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd'T'HH:mm:ss") private Date createTime; }
|
动态SQL
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
<select id="selectByUserSelective" resultType="com.miao.domain.User" parameterType="com.miao.domain.User"> select <include refid="Base_Column_List" /> from t_user where 1=1 <if test="userName != null and userName !='' "> and user_name like concat('%',#{userName},'%') </if> <if test="school != null and school !='' "> and school like concat('%',#{school},'%') </if> <if test="gender != null "> and gender= #{gender} </if> <if test="createTime != null "> and DATE_FORMAT(create_time,'%Y%m') = #{createTime} </if> </select>
|
在MySQL中查询
1 2 3 4 5 6 7
| mysql> select user_name , gender , create_time from t_user where 1=1 and user_name like'%d%' and gender = 1 and DATE_FORMAT(create_time,'%Y') =2013; +-------------+--------+---------------------+ | user_name | gender | create_time | +-------------+--------+---------------------+ | Ando Minato | 1 | 2013-08-23 13:29:45 | +-------------+--------+---------------------+ 1 row in set (0.03 sec)
|
代码测试
1 2 3 4 5 6 7 8 9 10 11 12
| @Test public void testSelect(){ Date date= new Date(); date.setYear(113); date.setMonth(7); User user = new User(); user.setUserName("d"); user.setGender(1); user.setCreateTime(date); List<User> users = userMapper.selectByUserSelective(user); users.forEach(System.out::println); }
|
问题
查询不到数据
需要注意日期的格式问题
我们必须提前预定好格式
需要注意的是, java在传入时间的时候传入的是时间戳 , 并且如果在查询的时候日期的格式中包含了 -
, 后面拼接的值只能是字符串
mybatis-plus执行语句
mybatis Date类型和Timestamp隐式转换问题,导致sql执行变慢。_y-yyl的博客-CSDN博客_mybatis timestamp转date
MySQL控制台
但是我们可以看到mybatis在查询的时候传入的createTime 的类型是timeStamp , 因此如果我们直接按照
and DATE_FORMAT(create_time,'%Y%m') = #{createTime}
, 查询, 一定是查询不到数据的 ,
原本纠结了好一会, 一直想怎么转换java.util.Date
, 实际上我们直接使用MySQL的DATE_FORMAT
把穿进去的createTime
给格式化就可以了
那么新的SQL语句就是下面这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
<select id="selectByUserSelective" resultType="com.miao.domain.User" parameterType="com.miao.domain.User"> select <include refid="Base_Column_List" /> from t_user where 1=1 <if test="userName != null and userName !='' "> and user_name like concat('%',#{userName},'%') </if> <if test="school != null and school !='' "> and school like concat('%',#{school},'%') </if> <if test="gender != null "> and gender= #{gender} </if> <if test="createTime != null "> and DATE_FORMAT(create_time,'%Y-%m') = DATE_FORMAT(#{createTime},'%Y-%m') </if> </select>
|
另外需要注意的查询的时候日期的格式必须完全相同 , 不能多也不能少, 也需要注意-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| mysql> select create_time from t_user where DATE_FORMAT(create_time,'%Y%m') = 202211; +---------------------+ | create_time | +---------------------+ | 2022-11-02 10:01:08 | | 2022-11-03 20:25:35 | | 2022-11-05 23:34:16 | +---------------------+ 3 rows in set (0.03 sec)
mysql> select create_time from t_user where DATE_FORMAT(create_time,'%Y%m') = 20221102; Empty set
mysql> select create_time from t_user where DATE_FORMAT(create_time,'%Y%m%d') = 20221102; +---------------------+ | create_time | +---------------------+ | 2022-11-02 10:01:08 | +---------------------+ 1 row in set (0.03 sec)
|
多条件的分页查询
(MyBatis-Plus 分页查询以及自定义sql分页_IT贱男的博客-CSDN博客_mybatisplus 原生sql 分页
重构上面的方法为
IPage<User> selectByUserSelective(IPage<User> page,@Param("user")User user);
注意点
需要添加@Param
注解 , 否则在多个参数的情况下mybatis是无法自动获取到参数的名称的
会报错: parameter 'username' not found. available parameters are [arg1, arg0, param1, param2]
同时需要把sql语句中的userName
改成user.userName
=> 这里面的user应该与@Param
注解里面的value
保持一致
代码如下