2017-05-13 59 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); 

這假設模型屬性名是嚴格按照顯示在後。