繁体   English   中英

spring data jpa不必要的左连接

[英]spring data jpa unnecessary left join

我有以下型号:

在此输入图像描述

我希望所有Institutions (Intituciones)都有指定的sectorId

tbInstitucion模型中,我与tbSector有关系:

 @ManyToOne(fetch=FetchType.LAZY)
 @JoinColumn(name="`sectorId`")
 private Sector sector;

有没有办法获得如下查询:

select * 
from tbInstitucion 
where sectorId = ?

我尝试过: findBySector(Sector sector)

但有了这个,我需要一个额外的查询来查找扇区, findBySector正在生成以下查询:

select
        generatedAlias0.institucionId,
        generatedAlias0.institucionNombre 
    from
        Institucion as generatedAlias0 
    left join
        generatedAlias0.sector as generatedAlias1 
    where
        generatedAlias1=:param0

试过另一个:

findBySector_sectorId

它也会生成上述查询。

形成如下查询不会更好:

select * 
from tbInstitucion 
where sectorId = ?

有没有办法获得上述查询? 为什么JPA会产生左连接?

快速回顾实体模型

@Entity
class Institucion {
  @ManyToOne(fetch=FetchType.LAZY)
  @JoinColumn(name="`sectorId`")
  private Sector sector;
}

相当于:

@Entity
class Institucion {
  @ManyToOne(cascade = {}
             , fetch=FetchType.LAZY
             , optional = true
             , targetEntity = void.class)
  @JoinColumn(columnDefinition = ""
             , foreignKey = @ForeignKey
             , insertable = true
             , name="`sectorId`"
             , nullable = true
             , referencedColumnName = ""
             , table = ""
             , unique = false
             , updatable = false)
  private Sector sector;
}

注意@ManyToOne(optional = true)@JoinColumn(nullable = true) 这向ORM表明Institucionsector属性是可选的,并且可能不会一直设置(到非空值)。


实体模型如何影响存储库查询

现在考虑以下存储库:

public interface InstitucionRepository extends CrudRepository<Institucion, Long> {
  List<Institucion> findAllByInstitucionNombre(String nombre);

  List<Institucion> findAllByInstitucionEmail(String email);
}

鉴于上面的实体声明,存储库方法应该产生如下查询:

select
    generatedAlias0 
from
    Institucion as generatedAlias0 
left join
    generatedAlias0.sector as generatedAlias1 
where
    generatedAlias0.institucionNombre=:param0

select
    generatedAlias0 
from
    Institucion as generatedAlias0 
left join
    generatedAlias0.sector as generatedAlias1 
where
    generatedAlias0.institucionEmail=:param0

这是因为实体模型表明sector是可选的,因此ORM需要加载Institucion而不必担心它们的sector

遵循此模式,以下存储库方法:

  List<Institucion> findAllBySector(Sector sector);

翻译为:

select
    generatedAlias0 
from
    Institucion as generatedAlias0 
left join
    generatedAlias0.sector as generatedAlias1 
where
    generatedAlias1=:param0

解决方案1

如果Institucion.sector不是可选的,也可以在模型中强制使用它:

  @ManyToOne(fetch=FetchType.LAZY, optional = false)
  @JoinColumn(name="`sectorId`", nullable = false)
  private Sector sector;

解决方案2

如果Institucion.sector确实是可选的,那么只有手动查询(例如@ MaciejKowalski的答案中显示的查询)才有效。


简化查询

以下查询也将起作用:

  List<Institucion> findAllBySectorSectorId(Long id);

这假设模型属性名称与帖子中显示的完全相同。

左连接是默认的隐式连接策略,也是在使用@EntityGraph功能时。

我建议使用显式的@Query定义:

@Query("select i from institution i inner join i.sector s where s.id = :sectorId")
public Institution getBySector(@Param("sectorId") Integer sectorId); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM