2017-05-13 30 views
2

我有以下型号:弹簧数据的JPA不必要的左连接

enter image description here

我想所有Institutions(Intituciones)与指定sectorId

tbInstitucion模型我有tbSector的关系:

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

是有办法获得查询,如:findBySector(Sector sector)

但:

select * 
from tbInstitucion 
where sectorId = ? 

我试过这我需要一个额外的查询来找到扇区和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生成左连接?

回答

1

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

我会建议使用明确定义@Query

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

但是为什么它会生成一个连接,不会更好一个select * from tbInstitucion where sectorId =? – rena

+0

那不是你如何在orm中编写查询..你得到了依赖实体..然后你得到它的id。 –

3

实体模型

@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表明属性Institucion是可选的,并且可能一直未设置(为非空值)。


如何实体模型的影响库查询

现在考虑下面的库:

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

这假设模型属性名是严格按照显示在后。