有时候,我们的分页查询接口的查询结果,需要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集合去查询额外的数据。
下面的示例是更加通用的根据参数查询需要关联的数据
- 定义 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 + "'}"; }
}
- 编写查询函数 目标类的查询方法 假设我们有一个简单的查询函数,它从数据库或其他数据源中获取用户列表。
public class UserService {
public List<User> getUsersByNames(List<String> keys) {
// 查询方法 lambdaQuery
}
}
- 调用 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 中。
}
}