
数据库有一些数据,如下模拟;
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 直接让前端传 sql 语句吧,他们爱查啥查啥…… |
7 EscYezi 2022-04-17 19:08:36 +08:00 via iPhone 看场景都是同一些数据同一些字段数值不同。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/span> MoozLee 2022-04-18 10:48:50 +08:00 graphql? |
12 BrbiwsFtd9zDGZqB 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 |