java springframework.data.jpa使用JpaSpecificationExecutor生成两次相同的连接

java springframework.data.jpa使用JpaSpecificationExecutor生成两次相同的连接,java,jpa,spring-data-jpa,Java,Jpa,Spring Data Jpa,我正在使用JpaSpecificationExecutor,所以我使用org.springframework.data.jpa.domain.specification中的规范Api动态创建sql,问题是它两次生成相同的连接,这会降低性能,下面是代码: 调用方方法是: private Specification<EntityA> toSpecEntityBAndEntityC(boolean withEntityBAndEntityC, Specification<Entity

我正在使用JpaSpecificationExecutor,所以我使用org.springframework.data.jpa.domain.specification中的规范Api动态创建sql,问题是它两次生成相同的连接,这会降低性能,下面是代码:

调用方方法是:

private Specification<EntityA> toSpecEntityBAndEntityC(boolean withEntityBAndEntityC, Specification<EntityA> specs) {
        if (withEntityBAndEntityC) {
            specs = Specification.where(specs).and(EntityASpecs.withEntityB());
            specs = Specification.where(specs).and(EntityASpecs.withEntityC());
        }
        return specs;
    }
它生成这个查询

  select *
from (select entityA0_.id                    as id1_4_0_,
             entityC2_.filedOne                  as filedOne1_3_1_,
             entityB3_.filedTwo                       as filedTwo1_1_2_,
             entityA0_.filedFive_id       as filedFive_id7_4_0_,
             entityA0_.entityB_filedTwo             as entityB_filedTwo8_4_0_,
             entityA0_.DATE_TRAITEMENT       as DATE_TRAITEMENT2_4_0_,
             entityA0_.filedFour               as filedFour3_4_0_,
             entityA0_.entityC_filedOne        as entityC_filedOne9_4_0_,
             entityA0_.filedSix                  as filedSix4_4_0_,
             entityA0_.filedSeven                as filedSeven5_4_0_,
             entityA0_.TEMPS_REPONSE         as TEMPS_REPONSE6_4_0_,
             entityC2_.NB_MOYEN_TRAITEMENTS as NB_MOYEN_TRAITEMEN2_3_1_,
             entityC2_.filedSeven               as filedSeven3_3_1_,
             entityC2_.filedSixteen    as filedSixteen4_3_1_,
             entityB3_.filedFifteen        as DATE_TRAITEMENT_SA2_1_2_,
             entityB3_.filedEight                as filedEight11_1_2_,
             entityB3_.filedTen               as filedTen3_1_2_,
             entityB3_.filedNine                    as filedNine4_1_2_,
             entityB3_.filedFourteen                    as filedFourteen5_1_2_,
             entityB3_.filedThirteen                        as filedThirteen6_1_2_,
             entityB3_.NUMERO_AUTORISATION        as NUMERO_AUTORISATIO7_1_2_,
             entityB3_.filedEleven                 as filedEleven8_1_2_,
             entityB3_.filedSeven                     as filedSeven9_1_2_,
             entityB3_.filedTwelve                   as filedTwelve10_1_2_
      from entityA entityA0_
             inner join entityB entityB1_ on entityA0_.entityB_filedTwo = entityB1_.filedTwo
             inner join entityC entityC2_ on entityA0_.entityC_filedOne = entityC2_.filedOne
             **inner join entityB entityB3_ on entityA0_.entityB_filedTwo = entityB3_.filedTwo**
      where entityA0_.filedSix = 'Value'
        and (entityB1_.filedFifteen between TO_DATE('2018-11-08 14:00:00', 'YYYY-MM-DD HH24:MI:SS') and TO_DATE('2018-11-08 15:00:00', 'YYYY-MM-DD HH24:MI:SS'))
      order by entityA0_.DATE_TRAITEMENT desc)
;
注意:

重复连接在两个星星之间

**inner join entityB entityB3_ on entityA0_.entityB_filedTwo = entityB3_.filedTwo**

初始规范是如何构建的?我指的是由
spects
参数传递到
tospecitybandentityc
方法中的一个。它的构造类似于规范toSpecs(boolean with antitybandentitic){Specification specs=Specification.where(null);我首先将断点放在
JoinScope::addJoin()处
并跟踪来自意外来源的呼叫
  select *
from (select entityA0_.id                    as id1_4_0_,
             entityC2_.filedOne                  as filedOne1_3_1_,
             entityB3_.filedTwo                       as filedTwo1_1_2_,
             entityA0_.filedFive_id       as filedFive_id7_4_0_,
             entityA0_.entityB_filedTwo             as entityB_filedTwo8_4_0_,
             entityA0_.DATE_TRAITEMENT       as DATE_TRAITEMENT2_4_0_,
             entityA0_.filedFour               as filedFour3_4_0_,
             entityA0_.entityC_filedOne        as entityC_filedOne9_4_0_,
             entityA0_.filedSix                  as filedSix4_4_0_,
             entityA0_.filedSeven                as filedSeven5_4_0_,
             entityA0_.TEMPS_REPONSE         as TEMPS_REPONSE6_4_0_,
             entityC2_.NB_MOYEN_TRAITEMENTS as NB_MOYEN_TRAITEMEN2_3_1_,
             entityC2_.filedSeven               as filedSeven3_3_1_,
             entityC2_.filedSixteen    as filedSixteen4_3_1_,
             entityB3_.filedFifteen        as DATE_TRAITEMENT_SA2_1_2_,
             entityB3_.filedEight                as filedEight11_1_2_,
             entityB3_.filedTen               as filedTen3_1_2_,
             entityB3_.filedNine                    as filedNine4_1_2_,
             entityB3_.filedFourteen                    as filedFourteen5_1_2_,
             entityB3_.filedThirteen                        as filedThirteen6_1_2_,
             entityB3_.NUMERO_AUTORISATION        as NUMERO_AUTORISATIO7_1_2_,
             entityB3_.filedEleven                 as filedEleven8_1_2_,
             entityB3_.filedSeven                     as filedSeven9_1_2_,
             entityB3_.filedTwelve                   as filedTwelve10_1_2_
      from entityA entityA0_
             inner join entityB entityB1_ on entityA0_.entityB_filedTwo = entityB1_.filedTwo
             inner join entityC entityC2_ on entityA0_.entityC_filedOne = entityC2_.filedOne
             **inner join entityB entityB3_ on entityA0_.entityB_filedTwo = entityB3_.filedTwo**
      where entityA0_.filedSix = 'Value'
        and (entityB1_.filedFifteen between TO_DATE('2018-11-08 14:00:00', 'YYYY-MM-DD HH24:MI:SS') and TO_DATE('2018-11-08 15:00:00', 'YYYY-MM-DD HH24:MI:SS'))
      order by entityA0_.DATE_TRAITEMENT desc)
;
**inner join entityB entityB3_ on entityA0_.entityB_filedTwo = entityB3_.filedTwo**