数据库有一些数据,如下模拟;
        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 总是获取所有的数据,针对流根据业务进行业务操作。
——————————
以上两种方法是否可行? 问题?
|      1PerFectTime      2022-04-17 16:06:08 +08:00 我们是维护了一个数据列表的列视图权限,在此基础上通过列视图的数据类型(bit/string/字典)由可配置的高级查询功能可以对每一列的情况进行筛选 | 
|      2eggoxygen      2022-04-17 16:26:25 +08:00 via iPhone 根据 ORM 框架不同有不同解决方案吧。 比如 JPA 的 Specification / QueryDsl 。 定义好需要查询的 Condition / Criteria 。 查询时传入即可。 | 
|      3Leviathann      2022-04-17 16:26:32 +08:00 为什么不根据查询条件动态生成 sql | 
|  |      4xiangyuecn      2022-04-17 17:16:50 +08:00 多写一条 if else 就要被抓取坐牢 | 
|      5micean      2022-04-17 17:52:35 +08:00 比如某个男人的 apijson…… | 
|  |      6lower      2022-04-17 17:57:56 +08:00  2 直接让前端传 sql 语句吧,他们爱查啥查啥…… | 
|  |      7EscYezi      2022-04-17 19:08:36 +08:00 via iPhone  1 看场景都是同一些数据同一些字段数值不同。controller 层只需要一个接口,定义一个含有多个字段的 vo ,本次查询用不到的字段和前端协商一个默认值就 ok dao 层 mybatis 的 xml 文件中 if 和 choose 根据各种情况拼接查询条件; mybatis-plus 也可以在拼接查询条件时增加 bool 参数指定是否拼接 全部查询出来数据少还好,多起来一次拿几十万数据出来,数据库和 java 服务压力都很大 | 
|  |      8letitbesqzr      2022-04-17 22:05:26 +08:00 试试用 Aviator 之类的表达式解析工具? 让前端传表达式 | 
|  |      9rehoni      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 的条件构造器。 | 
|      10whatevers      2022-04-18 10:03:36 +08:00 单表查询用 Mybatis 逆向工程生成 Mapper ,前端传参生成动态 sql | 
|  |      11MoozLee      2022-04-18 10:48:50 +08:00 graphql? | 
|      12BrbiwsFtd9zDGZqB      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 | 
|      13aguesuka      2022-04-18 14:07:12 +08:00 前端到后端用 luence 语法, 后端映射到 sql |