当前位置: 首页 > 知识库问答 >
问题:

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

况喜
2024-08-21

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;
}

共有1个答案

莫兴言
2024-08-21

在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查询问题,使用适当的索引等。
    • 如果可能,减少从数据库加载的数据量,只查询需要的字段。
 类似资料:
  • 我正在对一个小表执行一个简单的查询 系统表只有三列(Id、Name、Progress)和1300行。 我获取数据的代码是: 这段代码在JTable中显示日期大约需要15秒,而如果在phpmyadmin中执行查询,则需要不到1秒。

  • 本文向大家介绍sqlalchemy 将查询结果转换为字典,包括了sqlalchemy 将查询结果转换为字典的使用技巧和注意事项,需要的朋友参考一下 示例 首先为示例进行设置: 如果您要分别查询列,则该行是KeyedTuple具有_asdict方法的。方法名称以单个下划线开头,以匹配namedtupleAPI(它不是私有的!)。 使用ORM检索对象时,默认情况下不可用。应该使用SQLAlchemy检

  • 我正在尝试实现REST API,其中一部分是将数据格式化为JSON。我能够从mysql数据库中检索数据,但是我收到的对象并不是我所期望的。这是我的代码 结果: 如何实现返回如下所示的json格式:

  • 我有两个表TABLE_A,列名为COLUMN1 COLUMN2 COLUMN3 COLUMN 4 COLUM5 abc def ghi jkl mno 123 456 789 001 121 TABLE_B列名为COLUMN6 COLUMN7,其数据为 专栏5 124 第4列bca 第3列aaa 列5 BBB 所以我将Table_A的列名作为Table_B中的数据 所以我想在一个查询中做这样的事情

  • 我在项目中使用Spring数据JPA。当我要求一份特定导演制作的电影列表时,我得到: 电影拍摄地点: 董事报告人: 人员存储库: 电影控制器: 我不明白为什么当sql查询一切正常工作时,但是当使用表达式搜索存储库时,它却不能正常工作。在阅读了类似的问题后,我没有找到任何解决我问题的东西。 董事实体: 个人实体: 电影实体:

  • 我有以下表格结构: 1-课程(course_id、course_nam、语言、course_price、create_date、average_rating、course_description、certifica_price、course_creator_id) 2-学生(学生证、钱包) 3-折扣(折扣id、折扣课程id、允许的许可课程id、开始日期、结束日期、百分比) 4-报名(student