数据库有一些数据,如下模拟;
ArrayList<User> objects = Lists.newArrayList();
objects.add(new User("zhangsan", "123456", 18, 1));
objects.add(new User("lisi", "123456", 22, 1));
objects.add(new User("wangwu", "123456", 30, 1));
objects.add(new User("zhaoliu", "123456", 43, 1));
objects.add(new User("xiaoli", "xiaoli67889", 16, 0));
objects.add(new User("xiaona", "nai324389", 22, 0));
针对这些数据的查询而言,通常会在 service 层定义许多查询接口,例如
面对需求的变化多样,总是需要增量添加 controller 方法,service 方法,甚至 dao 方法,如何解决这个问题呢?
//dao
public static List<User> getUserList() {
ArrayList<User> objects = Lists.newArrayList();
objects.add(new User("zhangsan", "123456", 18, 1));
objects.add(new User("lisi", "123456", 22, 1));
objects.add(new User("wangwu", "123456", 30, 1));
objects.add(new User("zhaoliu", "123456", 43, 1));
objects.add(new User("xiaoli", "xiaoli67889", 16, 0));
objects.add(new User("xiaona", "nai324389", 22, 0));
return objects;
}
//service
public static Optional getUserListByPredicate(Predicate<User> predicate) {
List<User> userList = UserDao.getUserList();
ArrayList<Object> resultList = Lists.newArrayList();
for (User user : userList) {
if (predicate.test(user)) {
resultList.add(user);
}
}
return Optional.ofNullable(resultList);
}
//controller
public static void main(String[] args) {
//查询性别为男,年龄 20 以下,并且密码为默认密码 123456 的用户
Optional<List> result = UserService.getUserListByPredicate((User user) -> {
return user.getSex() == 1 && user.getAge() < 20 && user.getPassword().equals("123456");
});
result.get().stream().forEach(user -> System.out.println(user));
}
我的想法是,dao 层总是返回全量的数据(此处有问题性能问题),在 service 层对查询条件进行抽象,controller 只需要将查询条件传入即可。
//dao
public static List<User> getUserList() {
ArrayList<User> objects = Lists.newArrayList();
objects.add(new User("zhangsan", "123456", 18, 1));
objects.add(new User("lisi", "123456", 22, 1));
objects.add(new User("wangwu", "123456", 30, 1));
objects.add(new User("zhaoliu", "123456", 43, 1));
objects.add(new User("xiaoli", "xiaoli67889", 16, 0));
objects.add(new User("xiaona", "nai324389", 22, 0));
return objects;
}
//controller 层
/**
* 查询性别为男,年龄 20 以下,并且密码为默认密码 123456 的用户
*
* @param args
*/
public static void main(String[] args) {
List<User> userList = UserDao.getUserList();
userList.stream().filter(
user -> user.getSex() == 1 && user.getAge() < 20 && user.getPassword().equals("123456")
).forEach(user -> System.out.println(user));
}
我的想法是,controller 总是获取所有的数据,针对流根据业务进行业务操作。
——————————
以上两种方法是否可行? 问题?
1
PerFectTime 2022-04-17 16:06:08 +08:00
我们是维护了一个数据列表的列视图权限,在此基础上通过列视图的数据类型(bit/string/字典)由可配置的高级查询功能可以对每一列的情况进行筛选
|
2
eggoxygen 2022-04-17 16:26:25 +08:00 via iPhone
根据 ORM 框架不同有不同解决方案吧。
比如 JPA 的 Specification / QueryDsl 。 定义好需要查询的 Condition / Criteria 。 查询时传入即可。 |
3
Leviathann 2022-04-17 16:26:32 +08:00
为什么不根据查询条件动态生成 sql
|
4
xiangyuecn 2022-04-17 17:16:50 +08:00
多写一条 if else 就要被抓取坐牢
|
5
micean 2022-04-17 17:52:35 +08:00
比如某个男人的 apijson……
|
6
lower 2022-04-17 17:57:56 +08:00 2
直接让前端传 sql 语句吧,他们爱查啥查啥……
|
7
EscYezi 2022-04-17 19:08:36 +08:00 via iPhone 1
看场景都是同一些数据同一些字段数值不同。controller 层只需要一个接口,定义一个含有多个字段的 vo ,本次查询用不到的字段和前端协商一个默认值就 ok
dao 层 mybatis 的 xml 文件中 if 和 choose 根据各种情况拼接查询条件; mybatis-plus 也可以在拼接查询条件时增加 bool 参数指定是否拼接 全部查询出来数据少还好,多起来一次拿几十万数据出来,数据库和 java 服务压力都很大 |
8
letitbesqzr 2022-04-17 22:05:26 +08:00
试试用 Aviator 之类的表达式解析工具? 让前端传表达式
|
9
rehoni 2022-04-18 08:29:55 +08:00
定义一个通用的查询过滤器 Qo 数组,用作查询条件的拼接。当数组为空时,默认查全部 sql 为 select*;数组中每个对象对应一个条件,如年龄 20 以下、默认密码是 123456 ,拼接出来 sql 就是 select * where age < 20 ,pwd = ‘123456’; Qo 对象的 JSON 很明显包含字段名 age ,条件<,值 20 等,这是最基础的,然后在此 JSON 基础上还可以做一些拓展,如复杂字段建立驼峰关系或者建立映射,条件提供枚举,时间类型提供格式化,整体条件提供前端解决方案如指定为下拉框、时间选择器,再者就是可以利用框架特性来进行条件 Qo 的封装来实现通用效果,如 mybatis-plus 的条件构造器。
|
10
whatevers 2022-04-18 10:03:36 +08:00
单表查询用 Mybatis 逆向工程生成 Mapper ,前端传参生成动态 sql
|
11
li746224 2022-04-18 10:48:50 +08:00
graphql?
|
12
90d0n 2022-04-18 11:17:51 +08:00
1. mybatis, 用 myabtis-plus 的 QueryWrapper, 动态拼接一下查询条件.
https://baomidou.com/pages/10c804 2. jpa, 看文档 4.8.2 那一节, Querydsl Web Support. https://docs.spring.io/spring-data/jpa/docs/current/reference/html 实现后接口大概是这样: http://your.api/user?name=Alice&page=0&size=20&sort=age,asc |
13
aguesuka 2022-04-18 14:07:12 +08:00
前端到后端用 luence 语法, 后端映射到 sql
|