Java 休眠条件OneToOne FetchType.Eager FETCHTMODE.Join执行不必要的查询是

Java 休眠条件OneToOne FetchType.Eager FETCHTMODE.Join执行不必要的查询是,java,hibernate,hibernate-criteria,Java,Hibernate,Hibernate Criteria,我有示例实体TableA和TableB,在表A中我们有列table_B_ID,注释如下: @OneToOne(fetch = FetchType.EAGER, optional = false) @JoinColumn(name = "TABLE_B_ID") @Fetch(FetchMode.JOIN) 然后,当我执行如下简单代码时: Criteria c = session.createCriteria(TableA.class); c.list(); Hibernate运行查询n+1次

我有示例实体TableA和TableB,在表A中我们有列table_B_ID,注释如下:

@OneToOne(fetch = FetchType.EAGER, optional = false)
@JoinColumn(name = "TABLE_B_ID")
@Fetch(FetchMode.JOIN)
然后,当我执行如下简单代码时:

Criteria c = session.createCriteria(TableA.class);
c.list();
Hibernate运行查询n+1次,其中n=TableA中的行数,即使在第一次查询时TableA已经与TableB连接,Hibernate仍然试图通过另一个select查询为每个A获取TableB

已激发查询:

Hibernate: 
select
    this_.id as id1_0_1_,
    this_.name as name2_0_1_,
    this_.TABLE_B_ID as TABLE_B_3_0_1_,
    tableb2_.id as id1_1_0_,
    tableb2_.name as name2_1_0_ 
from
    TABLE_A this_ 
inner join
    TABLE_B tableb2_ 
        on this_.TABLE_B_ID=tableb2_.id
Hibernate: 
    select
        tablea0_.id as id1_0_1_,
        tablea0_.name as name2_0_1_,
        tablea0_.TABLE_B_ID as TABLE_B_3_0_1_,
        tableb1_.id as id1_1_0_,
        tableb1_.name as name2_1_0_ 
    from
        TABLE_A tablea0_ 
    inner join
        TABLE_B tableb1_ 
            on tablea0_.TABLE_B_ID=tableb1_.id 
    where
        tablea0_.TABLE_B_ID=?
Hibernate: 
    select
        tablea0_.id as id1_0_1_,
        tablea0_.name as name2_0_1_,
        tablea0_.TABLE_B_ID as TABLE_B_3_0_1_,
        tableb1_.id as id1_1_0_,
        tableb1_.name as name2_1_0_ 
    from
        TABLE_A tablea0_ 
    inner join
        TABLE_B tableb1_ 
            on tablea0_.TABLE_B_ID=tableb1_.id 
    where
        tablea0_.TABLE_B_ID=?
等等

我已经尝试删除
FetchMode
或更改
optional=true
,但仍然触发了n+1次查询。
即使hibernate已经获得了第一个select查询中的数据,他仍会触发另一个select的原因是什么?

您遇到了一个众所周知的问题,当您选择一个父实体时,会出现“N+1 selects”问题,hibernate将对与OneToOne父实体相关的子实体进行额外选择。因此,如果数据库中有“N”个父子记录,hibernate将通过一次选择获取所有父项,然后在单独的选择中获取每个子项,使总选择数为N+1。 对于hibernate中的“N+1”问题,有两种方法: 1.“加入并取回”所有OneTONE儿童。 2.启用二级缓存并在OneTONE子级上使用@cache注释

你的问题是你没有“加入”所有的OneToOne孩子。您必须“连接”它们,包括可传递的子对象(从子对象本身或集合中引用的实体)


使OneToOne变为懒惰(因为默认情况下它是渴望的)只是部分解决方案,因为hibernate只有在您访问子对象上的某个getter时才会为该子对象进行选择,但从长远来看,它仍然会进行所有N次选择。

您是否尝试过使用FetchType.LAZYI想要渴望的加载您是否尝试过内部/外部联接!可能是tableB比tableA多了一行。这只是一个示例表,所以没有您提到的复杂性,您可以看到第一个连接应该满足所有需要的信息,所以这与获取问题无关@缓存也不起作用。