zoukankan      html  css  js  c++  java
  • 扩展Spring-data-jpa导致注解@NamedEntityGraphs失效

    问题场景:
    在项目开发时,需要将一部分接口抽取到数据访问层中,于是对repository进行了扩展,新增了dao接口以及对应的repositoryImpl实现类。但是当运行时,发现使用JPA2.1注解@NamedEntityGraph解决的N+1问题又出现了。
     
    猜测:
    1.扩展repository导致实体类的@NamedEntityGraph注解失效。
    2.扩展repository导致repository中的@EntityGraph失效
     
    准备:分别对两个实体类都添加@NamedEntityGraph注解,并且在repository中override findAll方法。
    A:

    B:

    区别:为AllSettleRepository接口添加扩展 AllSettleDao接口和AllSettleRepositoryImpl实现类
    (以下简称为A,B)
    首先我在
    org.hibernate.jpa.graph.internal.EntityGraphImpl#getAttributeNodes‘打上断点。分别执行两个findAll方法,然后发现A没有进入该方法获取相关NamedEntityGraph的配置信息。B进入了该方法。
    继续跟踪到上一步,

    Spring-data-jpa在这一步执行query操作,并且去注入@EntityGraph的配置,查看query,其中有一个属性为entityGraphQueryHint,该属性存储方法配置的entityGraph信息。

    可以明显的看出,两者的区别在于A没值,B有值。
    然后往上跟踪找到Query注入该注解的位置
    然后找到了这段代码

    此时可以得知,jpa是在构造query时,从metadata中获取到对应的Graphs,然后注入到query中,但是前提时metadata不能为空。那么是不是因为A的metadata为空导致的呢
     
    继续往上跟踪
    在org.springframework.data.repository.core.support.RepositoryComposition.RepositoryFragments#invoke中

    spring-data-jpa会去查找repository的实现类
    重点:
    A由于我们自定义了一个实现类,所以是可以找到对应的实现类的。

    当找到其实现类之后,不会直接使用,而是会通过cglib动态代理去生成一个代理类。

    而B由于没有自定义实现类,所以使用的是spring-data-jpa的默认实现类,此时再往下执行,Spring-data-jpa不会为默认的实现类去生成代理类。
    继续往上跟踪:

    在org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor.CrudMethodMetadataPopulatingMethodInterceptor#invoke中,通过断点可以得知,A和B的metadata都是存在的,并且读取一次之后会存入到Cache中

    至此,已经很明显了,导致n+1重新出现的原因是因为@EntityGraph注解没有注入到query中,而@EntityGraph是需要去metadata中获取的。而自定义了实现类之后spring-data-jpa是会去利用cglib为自定义的实现类生成一个代理类,此时会丢失原有的metadata(通过上面cglib代理类代码可知,在生成代理类时,并不会去获取repository接口中的注解信息)。从而导致@EntityGraph无法注入。
     
    总结:spring-data-jpa会在执行时 为自定义的实现类创建一个代理类,此时会丢失掉metadata,导致原有的metadata中的信息丢失。所以在使用@NamedEntityGraph和@EntityGraph时,不能自定义repository的实现类,而要使用默认的repository实现类。

  • 相关阅读:
    关于解决win10安装mongodb启动服务失败的解决办法
    python3 Debug报错 Traceback (most recent call last)
    centos7 iptable开放端口失败的总结
    操作系统
    大数据医疗
    软件相关
    射频消融仪产品相关
    YY/T 0664—2020《医疗器械软件 软件生存周期过程》 相关
    ISO19001相关
    GMP现场指导相关
  • 原文地址:https://www.cnblogs.com/ymqj520/p/14046986.html
Copyright © 2011-2022 走看看