SpringDataJPA--实际操作

Stream 流操作求和处理

1.项目中在实际操作JPA的时候,通常会结合对应的Stream流去使用,由于我个人的原因对Stream流式编程应用的不太熟练,对很多操作,都是一知半解的。下面就对Stream流在操作中用的比较多的东西做过实际的总结

采用Strema流进行数值求和的两种方式

1.直接通过mapToInt(Integer::intValue)这种形式去获取对应的值,最后去进行sum求和

python 复制代码
  int sum = list.stream().map(Person::getAge).mapToInt(Integer::intValue).sum();

2.通过summarizingInt这种方式去进行控制,可以更好的得出常用的平均值,最大值,最小值

ini 复制代码
IntSummaryStatistics collect = list.stream().collect(Collectors.summarizingInt(Person::getAge));

Stream流操作-- Java8 Stream Collectors.toMap 和stream().map()区别

1.在使用Stream流操作的时候,还有很多地方不清楚的,比如在最终使用collect操作的时候,需要进行相关的map映射.

但是有一点不清楚的就是stream().map(),和stream().collect(CollectionsUtils.toMap());的区别

ini 复制代码
Map<String, Integer> residentCountMap = residentVOS.stream().collect(Collectors.toMap(ActivityCountVO::getActivityId, ActivityCountVO::getCount));
java 复制代码
List<SimpleRecommendRuleDTO> resultList =recommendRuleList.stream().map(SimpleRecommendRuleDTO::new).collect(Collectors.toList());
  1. list.stream().map()

取出来某个值

ini 复制代码
List<SchemePriceDTO> ftiPriceDtos = ftiResourcePriceDTOS.stream()
.map(x -> x.getPrice()).collect(Collectors.toList());

从list中取出某个对象

ini 复制代码
List<EventDetail> eventDetailList= request.getEventDto().getEventDetails().stream().map(detail -> {
            EventDetail eventDetail = new EventDetail();
            eventDetail.setGroupDetailId(detail.getGroupDetailId());
            eventDetail.setOrderId(detail.getOrderId());
            return eventDetail;
        }).collect(Collectors.toList());
  1. Collectors.toMap 是把list转化为Map
ini 复制代码
 Map<String, HLogHBasePO> hLogHBasePOMap = 
 hLogHBasePOs.stream().collect(Collectors.toMap(k -> k.getLogId(), v -> v));

可以看出来上述的操作中.stream().map()是取值的操作,而Collectors.toMap()是转换的操作

下面的demo可以进一个操作

csharp 复制代码
       List<Person> list = new ArrayList<>();
        list.add(new Person(22, "xiaohong"));
        list.add(new Person(33, "xiaohong2"));
        list.add(new Person(44, "xiaohong3"));
        List<String> strings = list.stream().map(Person::getName).collect(Collectors.toList());
        Map<String, Person> personMap = list.stream().collect(Collectors.toMap(Person::getName, Function.identity()));
        System.out.println("将list转换为map"+personMap);
        
        System.out.println("取出list集合中的值,然后讲name组成一个集合"+strings);

下面我在项目中见的比较多地方在进行记录一下可以看到,stream().map,和Collectors.toMap()在实际中的区别

stream().map()通常会结合对应的Collectors.toMap进行联合应用

java 复制代码
List<ResidentReceiveDTO> resultList = residentReceive.getContent().stream().map(ResidentReceiveDTO::new).collect(Collectors.toList());
List<String> sitIds = resultList.stream().map(ResidentReceiveDTO::getSiteId).collect(Collectors.toList());
List<Site> sites = siteRepository.findAllById(sitIds);
Map<String, Site> siteMap = sites.stream().collect(Collectors.toMap(Site::getId, Function.identity()));

1.分析一下代码可以看到,第一行的主要思想是将对应的一个数据实体list,转换成为一个dto的list实体集。

2.下面转换完之后,在将dto 的list实体集取出里面的id属性字段在组合成一个list的Id属性集

3.之后就根据对应的ID的list集合去查询全部的实体list集合,通过全部的实体list集合就可以返回一map映射的列表对象

4.后面这个转换的是,就是结合Collectors.toMap(sIT::getId,Function.identity()),这个Function.identity()这个属性字段通常用来作为value,这个是什么意思呢

官方的解释很笼统:Java 8允许在接口中加入具体方法。接口中的具体方法有两种,default方法和static方法,identity()就是Function接口的一个静态方法。

Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如t -> t形式的Lambda表达式。

下面通过搜查资料发现这个Function.identity()方法返回的就是自己;

identity() 方法JDK源码如下:

javascript 复制代码
static  Function identity() {
    return t -> t;
}

展示一个按理来进行操作

arduino 复制代码
// 将Stream转换成容器或Map
Stream<String> stream = Stream.of("I", "love", "you", "too");
Map<String, Integer> map = stream.collect(Collectors.toMap(Function.identity(), String::length));

Function.identity()的应用

下面的代码中,Task::getTitle需要一个task并产生一个仅有一个标题的key。task -> task是一个用来返回自己的lambda表达式,上例中返回一个task。

arduino 复制代码
private static Map<String, Task> taskMap(List<Task> tasks) {
  return tasks.stream().collect(toMap(Task::getTitle, task -> task));
}

Function.identity() or t->t?

rust 复制代码
Arrays.asList("a", "b", "c")
          .stream()
          .map(Function.identity()) // <- This,
          .map(str -> str)          // <- is the same as this.
          .collect(Collectors.toMap(
                       Function.identity(), // <-- And this,
                       str -> str));        // <-- is the same as this.

上面的代码中,为什么要使用Function.identity()代替str->str呢?它们有什么区别呢?

在上面的代码中str -> str和Function.identity()是没什么区别的因为它们都是t->t。但是我们有时候不能使用Function.identity,看下面的例子:

ini 复制代码
List list = new ArrayList<>();
list.add(1);
list.add(2);

下面这段代码可以运行成功:

ini 复制代码
int[] arrayOK = list.stream().mapToInt(i -> i).toArray();

但是如果你像下面这样写:

ini 复制代码
int[] arrayProblem = list.stream().mapToInt(Function.identity()).toArray();

运行的时候就会错误,因为mapToInt要求的参数是ToIntFunction类型,但是ToIntFunction类型和Function没有关系。

(实际应用:)

可以看到了这个Function.identity()指的就是Regiser中具体的实体类

数据库操作

1.单个处理只有在用id查详情的时候会用到,但大部分业务都是批量操作的

大部分情况下,在进行操作的时候,很少会有进行findById并返回单个实体的这种操作情况,一般情况都是批量操作的这种情况,业务处理基本上入参都是ids,出参也是list集合这种,这个时候就需要进行findByidIn

arduino 复制代码
 List<Resident> findAllByDelFlagIsFalseAndIdIn(List<String> ids);
ini 复制代码
List<Resident> residents = residentRepository.findAllByDelFlagIsFalseAndIdIn(residentIds);

可以看到对应的相关的findByIdIn对应的相关的集合的内容都是通过批量查询进行操作的,在进行相关的业务操作的时候最好进行findByIdIn这种的操作方式进行操作

2.通常给DTO添加额外的字段需要进行补充的时候,可以采用下面的这种方式进操作,并且一般情况下不要在for循环中进行查询操作,这样的话可能会造成代码抛异常的情况,这种情况下就需要进行特殊的处理,但是正常的情况给DTO赋值其他字段有需要对应的主键ID,通过对应的循环实体里面的ID,然后再结合其他的查询获取到其他的DTO,给循环体里面的DTO赋值,这种操作一般都是按如下的方式进行处理操作;

ini 复制代码
        List<String> residentIds = resultList.stream().map(ResidentReceiveDTO::getResidentId).collect(Collectors.toList());
        List<Resident> residents = residentRepository.findAllByDelFlagIsFalseAndIdIn(residentIds);
        Map<String, Resident> residentMap = residents.stream().collect(Collectors.toMap(Resident::getId, Function.identity()));

        List<String> sitIds = resultList.stream().map(ResidentReceiveDTO::getSiteId).collect(Collectors.toList());
        List<Site> sites = siteRepository.findAllByDelFlagIsFalseAndIdIn(sitIds);
        Map<String, Site> siteMap = sites.stream().collect(Collectors.toMap(Site::getId, Function.identity()));

        resultList.forEach(l -> {
            Activity activity = activityService.findById(l.getActivityId());
            Resident resident = residentMap.get(l.getResidentId());
            Site site = siteMap.get(l.getSiteId());
            if (resident!=null){
                l.setResidentName(resident.getName());
                l.setCardType(resident.getCardType());
                l.setCardNo(resident.getCardNo());
            }

            if (site!=null){
                l.setSiteName(site.getName());
            }
            if(activity!=null){
                l.setActivityName(activity.getTitle());
                l.setProductName(activity.getProductName());
            }
            l.setPersonName(site.getAdminName());
            l.setCount(Arrays.stream(l.getProductNo().split(",")).count());
        });

通过主要的分析和概述之后,主要的特征为三部分的代码,

1.第一部分代码为,先将对应的DTO里面要设值的其他字段的ID部分拿出来,通常来说这个DTO里面的ID字段,可以同这个查询其他的实体,就像我注释中写的那样,但是那样很不规范。

2.经过改造之后,可以拿到DTO里面所有的IDS的属性字段的集合,然后在外面通过findByIDin可以拿到所有根据这个ID有关的实体的数据,可能是多条数据,

3.第三步,就是通过查出来的IDS的实体的集合,在进行转换,将对应的list转换成map的形式,这个时候就需要通过key,value的形式控制,在控制的是,key可以设置成这个IDS实体集中实体的ID字段,value可以进行设置为这个实体,进行映射额,那这个形式就需要通过Function.identity()这个通常就是返回对象自己的。

通常来说使用SpringDataJPA,必须要集合stream流操作,如果stream流不熟悉,在进行使用JPA的时候,在联合操作的时候会出现很多问题。

后面还是有很多不足的地方,还需要进行补充和提升

相关推荐
duration~36 分钟前
Maven随笔
java·maven
zmgst40 分钟前
canal1.1.7使用canal-adapter进行mysql同步数据
java·数据库·mysql
跃ZHD1 小时前
前后端分离,Jackson,Long精度丢失
java
blammmp1 小时前
Java:数据结构-枚举
java·开发语言·数据结构
暗黑起源喵1 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射
九圣残炎2 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge2 小时前
Netty篇(入门编程)
java·linux·服务器
Re.不晚3 小时前
Java入门15——抽象类
java·开发语言·学习·算法·intellij-idea
雷神乐乐3 小时前
Maven学习——创建Maven的Java和Web工程,并运行在Tomcat上
java·maven