本文默认大家都已熟悉MyBatis Plus基本 *** 作,不赘述。
MyBatis Plus 使用起来已然十分方便,但对于一个动态条件查询来说,我们如果不想书写xml,就可能写出如下代码:
@PostMapping("/list")
public Object list(@RequestBody UserVO user) {
LambdaQueryChainWrapper lqcw = new LambdaQueryChainWrapper<>(userService.getBaseMapper());
// 拼接动态条件
if(user != null){
if(user.getId() != null) {
lqcw = lqcw.eq(UserVO::getId, user.getId());
}
if(user.getUserName() != null) {
lqcw = lqcw.likeLeft(UserVO::getUserName, user.getUserName());
}
......
}
return userService.list(lqcw);
}
看起来依然是十分啰嗦,于是,我们来简单封装一个工具类,根据传入的对象,不为空的字段,就动态拼接查询条件。
首先,我们需要知道字段和条件之间的对应关系,比如,对于 username字段,要使用 eq, 还是 like呢?
这个我们可以用一个注解来映射他们的关系:
/**
* @Author zaiLuShang
* @see Condition
* @see WhereBuilder
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Where {
Condition value() default Condition.eq;
String column();
}
@AllArgsConstructor
@Getter
public enum Condition {
eq("eq"),
ne("ne"),
lt("lt"),
le("le"),
gt("gt"),
ge("ge"),
like("like"),
likeLeft("likeLeft"),
likeRight("likeRight");
private String expression;
}
接下来定义一个工具类,根据传入的实体对象,返回一个拼接完成的QueryWrapper查询对象。
/**
* @Author zaiLuShang
*/
@Slf4j
public class WhereBuilder {
private WhereBuilder() {
}
public static QueryWrapper build(T t) {
QueryWrapper queryWrapper = new QueryWrapper();
if (t == null) return queryWrapper;
QueryWrapper[] queryWrapperArr = new QueryWrapper[]{queryWrapper};
Class> tc = t.getClass();
Stream.of(tc.getDeclaredFields())
.peek(field -> field.setAccessible(true))
.filter(field -> {
try {
return field.get(t) != null
&& field.getAnnotation(Where.class) != null;
} catch (IllegalAccessException e) {
log.error("获取字段时异常:", e);
return false;
}
})
.forEach(field -> {
try {
Where where = field.getAnnotation(Where.class);
Condition condition = where.value();
String column = where.column();
Object value = field.get(t);
whereMap.get(condition).invoke(queryWrapperArr, column, value);
} catch (Exception e) {
log.error("执行条件拼接时异常:", e);
}
});
return queryWrapperArr[0];
}
private static Map[], String, Object>> whereMap = new HashMap<>() {{
put(Condition.eq, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].eq(column, value));
put(Condition.ne, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].ne(column, value));
put(Condition.lt, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].lt(column, value));
put(Condition.le, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].le(column, value));
put(Condition.gt, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].gt(column, value));
put(Condition.ge, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].ge(column, value));
put(Condition.like, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].like(column, value));
put(Condition.likeLeft, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].likeLeft(column, value));
put(Condition.likeRight, (queryWrapperArr, column, value) -> queryWrapperArr[0] = queryWrapperArr[0].likeRight(column, value));
}};
}
@FunctionalInterface
interface Con3 {
void invoke(P1 p1, P2 p2, P3 p3);
}
在实体类上打上注解:
/**
* 前台用户
*
* @Author zaiLuShang
*/
@Data
@Accessors(chain = true)
@TableName("bar_user")
public class UserVO extends BaseVO {
// 主键
@TableId(type = IdType.AUTO)
@Where(column = "id")
private Long id;
// 用户名
@Where(value = Condition.like, column = "username")
private String username;
// 昵称
@Where(value = Condition.like, column = "nickname")
private String nickname;
// 密码
private String password;
// 头像
private String avatar;
// 邮箱
private String email;
// 手机
private String mobile;
// 状态
@Where(value = Condition.eq, column = "status")
private String status;
}
接下来,在Controller 只需如下,便能完成sql的动态组装
@PostMapping("/list/{current}/{size}")
public Object list(@PathVariable Long current, @PathVariable Long size, @RequestBody UserVO user) {
return userService.page(new Page<>(current, size), WhereBuilder.build(user));
}
代码变得干净又卫生。
2022年1月27日 修订驼峰字段问题
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)