取消联表,分开查询通用方法

75 阅读2分钟

有时候,我们的分页查询接口的查询结果,需要join多张表才能查出数据。 比如在查询商品信息时,需要根据商品名称、单位、品牌、分类等信息查询数据。 这时候写一条sql可以查出想要的数据,比如下面这样的:

select p.id, p.product_name, u.unit_name, b.brand_name, c.category_name 
from product p 
inner join unit u on p.unit_id = u.id 
inner join brand b on p.brand_id = b.id 
inner join category c on p.category_id = c.id 
where p.name='测试商品' limit 0,20;

使用product表去join了unit、brand和category这三张表。 其实product表中有unit_id、brand_id和category_id三个字段。 我们可以先查出这三个字段,获取分页的数据缩小范围,之后再通过主键id集合去查询额外的数据。

下面的示例是更加通用的根据参数查询需要关联的数据

  1. 定义 User 类(需要联的类)
public class User{ 
    private Long id; 
    
    private String name; 
    
    public User(Long id, String name) 
    { this.id = id; this.name = name; } 
    
    public Long getId() 
    { return id; } 
    
    public String getName() 
    { return name; } 
    
    @Override public String toString() 
    { return "User{id=" + id + ", name='" + name + "'}"; } 
}
  1. 编写查询函数 目标类的查询方法 假设我们有一个简单的查询函数,它从数据库或其他数据源中获取用户列表。
    public class UserService { 
        public List<User> getUsersByNames(List<String> keys) { 
        // 查询方法 lambdaQuery 
        } 
    }
  1. 调用 queryByKeys 方法 查出关联的结果集合

现在我们可以编写一个示例来调用 queryByKeys 方法。 queryByKeys可以写在queryService里面,注入使用,或者创建一个基类commonserviceimpl去继承

    public class Main { public static void main(String[] args) { 
        @Autowired 
        private UserService userService; 
        
        List<String> names = Arrays.asList("1", "2", "3"); 
    
        // 下面因为篇幅把queryByKeys写在一起,实际上要抽离出来
        Map<String, User> userMap = queryService.queryByKeys ( 
            names, 
            userService::getUsersByNames, 
            User::getName ); //获取到的原先被联表的集合,后面手动关联 
        } 
    
        // Function<List<K>, List<T>> queryFunction 这个定义涉及两个类型参数 K 和 T,它们分别代表输入和输出的类型 
        public static <K, T> Map<K, T> queryByKeys(List<K> keys, Function<List<K>, List<T>> queryFunction, Function<T, K> keyExtractor) { 
            if (keys == null || keys.isEmpty()) {
                return Collections.emptyMap(); 
            } 
            List<T> resultList = queryFunction.apply(keys); 
            return resultList.stream() 
                .collect(Collectors.toMap(keyExtractor, Function.identity())); // Function.identity() 可以用于将 resultList 中的每个元素直接作为值放入 Map 中。
        } 
    }