我有一个实体
@Entity
@Table(name = "GEO_MUNICIPALITY", indexes = {
@Index(name = "idx_municipalityentity", columnList = "PROVINCE_CODE")
})
...
public class MunicipalityEntity {
@Id
@Column(name = "MUNICIPALITY_CODE", nullable = false)
private String code;
@Column(nullable = false)
private String name;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PROVINCE_CODE")
private ProvinceEntity province;
@ElementCollection
@CollectionTable(name = "GEO_MUNICIPALITY_POSTAL_CODE",
joinColumns = @JoinColumn(name = "MUNICIPALITY_CODE"),
indexes = {
@Index(name = "idx_municipalityentity_postal_code", columnList = "MUNICIPALITY_CODE")
})
@Column(name = "POSTAL_CODE")
private List<String> postalCodeList;
}
个字符
现在,我的API需要显示具有给定省份代码的所有城市(以及所有城市的邮政编码),因此我有一个像这样的存储库类:
@Repository
public interface MunicipalityJpaRepository extends JpaRepository<MunicipalityEntity, String> {
List<MunicipalityEntity> findAllByProvinceCode(String province);
@Query("select m from MunicipalityEntity m left join m.postalCodeList postalCodeList where m.province.code = ?1")
List<MunicipalityEntity> findByCode(String code);
}
型
这两个方法做同样的事情,我尝试了两种方式(结果是相同的),因为当我调用getPostalCodeList()
时,查询非常慢,因为它对市政当局的每个结果进行选择(检索邮政编码)。
我怎样才能提高性能?另外,因为我总是通过代码搜索市政当局,是一个好主意,使索引像在代码中?谢谢!
我尝试了使用jpa仓库和自定义查询,我期待一个快速的查询执行时间,但执行非常慢,因为在连接查询后,应用程序对每个结果城市进行查询,以获取邮政编码。
1条答案
按热度按时间2fjabf4q1#
在JPQL中,
left join
不是left join fetch
。如果我运行您的示例并尝试打印结果,我会得到可怕的LazyInitializationException
。您说过您会得到一个单独的PostalCodes查询,但这是因为您仍在Session
中访问邮政编码。这是您应该在应用程序中更好地设置的东西。我不再使用我的简单版本当我试图访问邮政编码时,我得到了LazyInitializationException
。与您的原始查询:
字符串
我得到这个SQL
型
如果我在H2-CONSOLE中运行该SQL,
x1c 0d1x的数据
这是混乱的,因为sql的结果是CARTESIAN PRODUCT,但它不包括POSTAL_CODE属性。
型
我得到正确的结果
型
如实际SQL中所示
的
请注意,似乎需要
@Query
来解决这个问题。在JPA中,您可以/应该使用ApertyGraphs来告诉JPA获取您想要的属性,这些属性通常不会被获取,例如postalCodeList。所以你可以用一个JPA
EntityGraph
来修复你的常规SpringDataJpa方法。型
如果我把它改成
型
然后我在SQL中得到你想要的
型
另外请注意,我没有特别打印出PROVINCE_CODE。如果我这样做,也会导致
LazyInitializationException
。型
给我
型
我说你应该在你的应用程序中更好地处理你的
Session
,因为如果你在初始查询之后访问了PROVINCE_CODE,它也会导致另一个查询。如果你确保你的会话只在你想要的JPA访问期间活动,那么你会得到一个LazyInitializationException
,而不是糟糕的性能。希望这能有所帮助。总是检查JPA生成的SQL查询,以确保你知道发生了什么。PS>你可能会问,当查询返回的是PROVINCE_CODE时,为什么要用
LazyInitializationException
来代替ProvinceEntity
呢?型
希望这对你有帮助。