MyBatisPlus 泛型方法使用default <V> List<V> listObjs(Function<? super Object, V> mapper)
一、泛型限制和函数式接口说明
1.1、带限制的泛型
default List listObjs(Function<? super Object, V> mapper)
首先 我们先看到的这个方法入参是:Function<? super Object , V> mapper
,这是jdk1.8为了统一简化书写格式引进的函数式接口 。简单 解释一下对Function函数的理解,就以上面的写法为例,可以看到Function函数要传入两个类型:
- ? super Object 这个类型限制了下限,即传入的类型必须是Object的超类,或者是Object ,所以函数的第一个类型必然是 Object类型 ,后面会说为什么会是Object类型
- V 没有限制泛型的上下边界,所以可以为任何类型
1.2、函数式接口
每个函数式接口的典型特点就是有且仅有一个可以实现的接口,Function也不例外;看下接口部分源码:
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
...
}
这个接口做的就是类型之间T和R的转换传入T类型 ,返回R类型。那么上面的Function<? super Object, V>写法就是说【传入Object类型,返回 V 类型】。
知识补充:
函数式(Functional)接口
泛型在继承上的体现【通配符】
二、MyBatisPlus listObjs 接口介绍
2.1、官网接口说明
// 查询全部记录
1. <V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
2. <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
接口源码
1. default List<Object> listObjs() {
return this.listObjs(Function.identity());
}
2. default <V> List<V> listObjs(Function<? super Object, V> mapper) {
return this.listObjs(Wrappers.emptyWrapper(), mapper);
}
3. default List<Object> listObjs(Wrapper<T> queryWrapper) {
return this.listObjs(queryWrapper, Function.identity());
}
4. default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
return (List)this.getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
}
可以看到接口源码中方法2调用了方法4。
2.2、方法4的意义
- this.getBaseMapper().selectObjs(queryWrapper):拿到BaseMapper;再调用它的selectObjs方法传入queryWrapper条件,查出数据list。
- stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList()):再利用流处理,过滤掉空值,筛选出mapper类型的数据,重新组成一个集合。
- 就得到了我们所需要的List数据。这个V类型就是我们上面所说的Function中所传的泛型V,就是我们想要转换的类型。
三、listObjs 使用示例
接下来看一下我们在Service业务方法中对Function的方法实现以及对listObjs()方法的调用。
3.1、实例化出Function接口
先实例化出Function接口,实现apply接口,进行类型转换,其中Object类型的参数是我们实体类中使用Mp的@TableId注解标注的属性。
##由于主键属性的类型不定,所以mp只能定为Object类型来限制传参。
##如果没有标注注解,则根据属性名对应数据库表的字段进行匹配查找(参数一般都是主键id,除非你使用@TableId注解标注了其他字段)。
Function<Object,Long> function = new Function<Object, Long>() {
@Override
public Long apply(Object id) {
//进行一系列转换操作 ,最终返回我们所需要的类型V , 这里只做简单演示。
return Long.valueOf(id.toString());
}
};
3.2、listObjs 调用
调用listObjs(queryWarpper,function)方法,这里queryWrapper就不做介绍。
List<Long> longs1 = listObjs(null, function);
经过Function的处理我们会得到表中数据的所有主键做组成的list集合。
3.3、方式使用另外两种写法
推荐最后一种。
//匿名类写法
List<Long> longs = listObjs(null, new Function<Object, Long>() {
@Override
public Long apply(Object id) {
//进行一系列转换操作 ,最终返回我们所需要的类型V , 这里只做简单演示。
return Long.valueOf(id.toString());
}
});
//简写
List<Long> longs = listObjs(null, a ->{
return Long.valueOf(a.toString());
});
3.4、返回其他对象类型示例
@Test
void mpTest() {
List<User> list = userService.list();
list.stream().forEach(System.out::println);
System.out.println("--------------------------------");
List<UserVo> longs = userService.listObjs(null, new Function<Object, UserVo>() {
@Override
public UserVo apply(Object id) {
System.out.println("apply的参数"+id.toString());
UserVo userVo = new UserVo();
User user = userService.getById(Integer.valueOf(id.toString()));
copyProperties(user,userVo);
return userVo;
}
});
longs.stream().forEach(System.out::println);
}