Hibernate为每个查询生成不同的SQL

我刚刚在探查器下测试了我的应用程序,发现sql字符串占用了大约30%的内存! 这很奇怪。

应用程序内存中存储了很多像这样的字符串。 这是由hibernate生成的SQL查询,请注意不同的数字和尾随下划线:

select avatardata0_.Id as Id4305_0_,...... where avatardata0_.Id=? for update select avatardata0_.Id as Id4347_0_,...... where avatardata0_.Id=? for update 

这是我无法理解的部分。 为什么hibernate必须为每个查询生成具有不同标识符的不同sql字符串,如“ Id4305_0_ ”? 为什么不能为所有相同的查询使用一个查询字符串? 这是绕过查询缓存的某种技巧吗?

如果有人能形容我为什么会这样,以及如何避免这种资源浪费,我将不胜感激。

UPDATE

好。 我找到了。 假设内存泄漏我错了,这是我的错。 Hibernate按预期工作。

我的应用程序在10个线程中创建了121(!)SessionFactories,它们生成了大约2300个SingleTableEntityPersisters实例。 每个SingleTableEntityPersister生成大约15个具有不同标识符的SQL查询。 Hibernate被迫生成大约345,000个不同的SQL查询。 一切都很好,没有什么奇怪的:)

hibernate生成的查询字符串背后有一个逻辑。 其主要目的是为表和列名称获取唯一的别名。

从您的查询,

select avatardata0_.Id as Id4305_0_,...... where avatardata0_.Id=?

avatardata0_ ==> avatardata是表的别名,附加0_表示它是查询中的第一个表。 因此,如果它是查询中的第二个表(或实体),它应该显示为avatardata1_ 。 它对列别名使用相同的逻辑。

因此,这样可以避免所有可能的冲突。

您正在查看这些查询,因为您已打开show_sql标志配置。 这用于调试查询。 一旦你的应用程序开始工作,你应该把它关掉。

在此处阅读有关API文档的更多信息 。

我不太了解内存消耗部分,但是你重复测试并关闭上面的标志,看看是否有任何改进。

假设您使用的是sql server,您可能需要检查’?’的参数类型声明,确保声明每次都产生相同的固定长度声明。

动态长度参数将导致每个查询的单独执行计划。 这可能会占用大量资源。 我们看到的是相同的过程,由sql server解释为另一个查询,呈现一个单独的执行计划。

从而,

 exec myprocedure @p1 varchar(3)='foo' 

 exec myprocedure @p1 varchar(6)='foobar' 

会导致不同的计划。 简单地说,@ p1的声明大小不同。

关于这种行为有很多要了解。 如果上述内容适用于您,我建议您阅读“参数嗅探”。

不…你可以在hibernate中生成常见的查询。 背后的逻辑是与表映射并从那里获取记录。 它用于所有数据库的通用查询。 请创建一个这样的常见查询:

示例:

 select t.Id as Id4305_0_,...... from t where t.Id=?