excel下载,查询结果转换model非常耗时,为什么?

springboot jpa查询结果转换成model非常耗时,查了一下,cpu一个核跑满了。

Cpu usage!
Found JVM pid:25370,topThreadHexIds=[ 479e,CPU_Usage:99.9 48a4,CPU_Usage:99.9 2fc,CPU_Usage:5.3 17dc,CPU_Usage:5.3]
------------------------*******0x48a4  CPU_Usage:99.9***********----------------------------
"default task-259" #7794 prio=5 os_prio=0 tid=0x0000565341845000 nid=0x48a4 runnable [0x00007f54b9c81000]
   java.lang.Thread.State: RUNNABLE
    at java.lang.System.identityHashCode(Native Method)
    at java.lang.reflect.WeakCache$LookupValue.hashCode(WeakCache.java:282)
    at java.util.concurrent.ConcurrentHashMap.get(ConcurrentHashMap.java:936)
    at java.util.concurrent.ConcurrentHashMap.containsKey(ConcurrentHashMap.java:964)
    at java.lang.reflect.WeakCache.containsValue(WeakCache.java:175)
    at java.lang.reflect.Proxy.isProxyClass(Proxy.java:791)
    at sun.reflect.annotation.AnnotationInvocationHandler.asOneOfUs(AnnotationInvocationHandler.java:225)
    at sun.reflect.annotation.AnnotationInvocationHandler.equalsImpl(AnnotationInvocationHandler.java:201)
    at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:64)
    at com.sun.proxy.$Proxy401.equals(Unknown Source)
    at org.springframework.core.convert.TypeDescriptor.annotationEquals(TypeDescriptor.java:504)
    at org.springframework.core.convert.TypeDescriptor.annotationsMatch(TypeDescriptor.java:494)
    at org.springframework.core.convert.TypeDescriptor.equals(TypeDescriptor.java:468)
    at org.springframework.core.convert.support.GenericConversionService$ConverterCacheKey.equals(GenericConversionService.java:471)
    at org.springframework.util.ObjectUtils.nullSafeEquals(ObjectUtils.java:329)
    at org.springframework.util.ConcurrentReferenceHashMap$Segment.findInChain(ConcurrentReferenceHashMap.java:648)
    at org.springframework.util.ConcurrentReferenceHashMap$Segment.getReference(ConcurrentReferenceHashMap.java:504)
    at org.springframework.util.ConcurrentReferenceHashMap.getReference(ConcurrentReferenceHashMap.java:265)
    at org.springframework.util.ConcurrentReferenceHashMap.get(ConcurrentReferenceHashMap.java:235)
    at org.springframework.core.convert.support.GenericConversionService.getConverter(GenericConversionService.java:256)
    at org.springframework.core.convert.support.GenericConversionService.canConvert(GenericConversionService.java:146)
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:127)
    at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590)
    at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:609)
    at org.springframework.beans.AbstractNestablePropertyAccessor.processLocalProperty(AbstractNestablePropertyAccessor.java:458)
    at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:278)
    at org.springframework.beans.AbstractNestablePropertyAccessor.setPropertyValue(AbstractNestablePropertyAccessor.java:246)

model类添加@EqualsAndHashCode还是会这样

model的大概结构,@Excel是自己写的一个注解用于excel导出,


@Setter
@Getter
@EqualsAndHashCode(callSuper = true)
public class D extends E{  
    
    //仓库
    @Excel(name = "仓库", sort = 5, align = HorizontalAlignment.LEFT)
    private String c;
    
    //业务类型
    private String b;
    @Excel(name = "业务类型", sort = 10, align = HorizontalAlignment.LEFT)
    private String a;
}
阅读 923
avatarAI BotBETA

在Spring Boot JPA应用中,将查询结果转换为Model对象时遇到的性能问题通常与以下几个方面相关:

  1. 复杂的类型转换和映射

    • 当使用JPA或Spring Data JPA时,Hibernate或底层ORM框架会负责将数据库查询结果转换为Java对象。这个过程中,如果实体(Entity)或DTO(数据传输对象)之间的映射非常复杂,或者使用了大量的自定义类型转换器,就可能导致性能问题。
  2. 大量的反射操作

    • 从你的堆栈跟踪来看,java.lang.reflect包下的方法被频繁调用,这通常与动态代理、反射访问字段或方法相关。在你的情况下,这可能与Spring的转换服务(如GenericConversionService)以及使用@EqualsAndHashCode等Lombok注解生成的代码有关。这些操作都可能导致较高的CPU使用率。
  3. @EqualsAndHashCode的使用

    • 虽然@EqualsAndHashCode注解可以方便地生成equals和hashCode方法,但在高并发或大数据量的情况下,这些方法可能会成为性能瓶颈,尤其是当它们涉及到复杂的对象图或继承结构时。此外,如果生成的hashCode方法导致大量的哈希冲突,也可能影响性能(如HashMap的性能下降)。
  4. 并发和线程管理

    • 如果你的应用是多线程的,并且线程之间竞争激烈(如多个线程尝试访问或修改同一个资源),也可能导致CPU使用率上升。

解决方案

  1. 优化映射和转换

    • 简化实体和DTO之间的映射关系,减少不必要的字段和关联。
    • 如果可能,使用DTO代替实体来减少加载的数据量。
    • 自定义转换器时,尽量减少反射的使用,直接通过字段访问或getter/setter方法。
  2. 减少反射操作

    • 考虑移除或替换那些可能导致高反射开销的库或注解,如评估@EqualsAndHashCode的必要性,并考虑手动实现这些方法或使用其他替代方案。
    • 如果使用了动态代理,请确保它们是必要的,并考虑优化或替换为更高效的实现。
  3. 并发和性能调优

    • 分析应用的并发模式和线程使用情况,确保没有资源争用或死锁。
    • 使用适当的并发工具和库(如Java并发包)来优化性能。
  4. 监控和性能分析

    • 使用Java性能分析工具(如JProfiler, YourKit, VisualVM等)来深入分析应用的性能瓶颈。
    • 监控CPU使用率、内存消耗、线程状态等指标,以便及时发现和解决问题。
  5. 数据库查询优化

    • 确保数据库查询是高效的,避免N+1查询问题,使用适当的索引等。
    • 如果可能,减少从数据库加载的数据量,只查询需要的字段。
1 个回答

由于查询包是公司框架封装好的,查看源码,发现如果接收的类型如果是Map,查询出来的result不会走属性、注释等校验,而是直接返回。遂换成Map接收,然后自己循环转换成model。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏