[英]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表明Institucion
的sector
属性是可选的,并且可能不会一直设置(到非空值)。
实体模型如何影响存储库查询
现在考虑以下存储库:
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.