我有以下型号:
我希望获得指定Institutions
的所有sectorId
(Intituciones)。
在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会产生左连接?
答案 0 :(得分:5)
快速回顾实体模型
@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表明sector
的{{1}}属性是可选的,并且可能不会一直设置(到非空值)。
实体模型如何影响存储库查询
现在考虑以下存储库:
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
是可选的,因此ORM需要加载sector
而不必担心他们的Institucion
。
遵循此模式,以下存储库方法:
sector
转换为:
List<Institucion> findAllBySector(Sector sector);
解决方案1
如果select
generatedAlias0
from
Institucion as generatedAlias0
left join
generatedAlias0.sector as generatedAlias1
where
generatedAlias1=:param0
不是可选的,请在模型中强制使用它:
Institucion.sector
解决方案2
如果 @ManyToOne(fetch=FetchType.LAZY, optional = false)
@JoinColumn(name="`sectorId`", nullable = false)
private Sector sector;
确实是可选的,那么只有@ MaciejKowalski答案中显示的手动查询才有效。
简化查询
以下查询也可以使用:
Institucion.sector
这假设模型属性名称完全如帖子所示。
答案 1 :(得分: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);