我在 hibernate 时遇到了一个Map问题。
在2个表之间获得此Map
表一
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name="CNT_ID",referencedColumnName = "CNT_ID",insertable = false, updatable = false)
@NotFound(action=NotFoundAction.IGNORE)
private Table2 table2;
表二
@OneToMany(mappedBy="table2")
private List<Table1> table1List;
我正在进行如下查询:
select table1 from Table1 table1 left outer join table1.table2
结果还行:获取了table 1和一些table 2中的所有数据(一些table 1没有到table 2的链接),因此外部连接正常。
问题是,Hibernate进行一次查询来捕获所有的table 1,并且在对table 1的每一行结果进行一次查询之后。因此,如果我在表1中有100行,Hibernate将进行101次查询...
我错过了什么吗?我正在使用oracle数据库,也尝试了(+)操作符(oracle中的外部操作符),但Hibernate不需要它。
谢谢你的帮助!
3条答案
按热度按时间omtl5h9j1#
首先,你需要将
table2
的fetch改为FetchType.LAZY
。如果你没有足够的理由去急切地获取关联的@ManyToOne
部分,就一定要这样做。如果需要获取在
table2
中具有某些属性的Table1
,只需使用连接from Table1 table1 left join table1.table2 table2 where table2.someProperty = :somePropertyValue
如果需要加载
table2
,请使用连接提取from Table1 table1 left join fetch table1.table2 table2 where table2.someProperty = :somePropertyValue
如果只需要
table2
的一部分,请使用投影select table1.property1, table1.property2, table2.someProperty from Table1 table1 left join table1.table2 table2 where table2.someProperty = :somePropertyValue
如果要使用投影,则可以使用
new
语法填充DTO对象select new com.pack.TableDto(table1.property1, table1.property2, table2.someProperty) from Table1 table1 left join table1.table2 table2 where table2.someProperty = :somePropertyValue
个也可以使用变压器。
pw9qyyiw2#
因为(parent)为“EAGER”(渴望),而您选择的是
Table1
,对于Table1
中的每一行,Hibernate都将发出一个查询来填充Table2
引用。一个解决方案是在第一个查询中加入fetchtable2
引用。这是Hibernate在使用HQL时的已知行为(与标准API,我不认为它适用).我已经在博客上详细介绍了它herenwnhqdif3#
这里的核心问题,正如topicstarter提到的,不是“父”表(表2)中的现有记录。在这种情况下,通过@Query中的左联接或使用@EntityGraph进行提取没有帮助。就像在表1的主查询中有一个外联接一样,您将有来自表2的额外N个查询。我不知道为什么在所有的解释“如何修复n+1查询问题”中忽略了这种情况,因为从数据库结构的Angular 来看,有外键而没有目标记录是绝对正常的情况。🤷♂️