我一直遇到一个问题,因为我们的数据库中存在过多的选择语句,我很好奇是否有人可以了解情况。我在下面提供的代码显示了似乎给我们带来问题的关系的基本结构。
我们使用@MappedSuperclass
为所有课程提供@Id
和@Version
。 A类和B类具有通过OccurrenceOfB
管理的多对多关系,但是还有与每个OccurrenceOfB
实例关联的额外信息(未显示)(因此我们不仅仅使用{ {1}})。
当我们尝试创建A的字符串表示时,问题就变得明显了。在这种情况下,我实际上构建了JSON,但是我在这里排除了大部分内容。下面包含的相关代码涉及迭代A中的所有JoinTable
并获取每个{的ID。但是,当我们这样做时(特别是,当迭代开始时),Hibernate正在检索所有OccurrenceOfB
个对象。这正如我所料。但是,与此同时,它还检索所有相应的B对象,以及与每个B相关联的C对象。换句话说,当它懒惰地检索OccurrenceOfB
时,它会急切地获取其余的实体图并且没有遵守OccurrenceOfBs
注释(根据文档,这只是一个提示)。这不是我所期望的 - 并且当A.occurrences的大小为数千时,会导致一些重要的性能命中。 (我们的实际对象稍微复杂一些,但是使用1500 FetchType.LAZY
序列化一个A会导致我们系统中的10502个select语句。)
奇怪的是,相反的情况并不成立。如果我有一个B出现在1500 As中,将B转换为字符串(同样遍历事件集合并检索每个字符串的ID)不会执行所有过多的select语句。
现在,最后还是实际问题:在这种情况下,如何提高数据库的性能?设置默认的批量提取大小可以提供一些缓解,但它似乎是对基础问题的创可贴。理想情况下,我如何说服Hibernate真正尊重传递关联的延迟提取?
OccurrenceOfB
后续: 所以,通过一些更多的调查,我认为我已经确定了问题 - 并且它不在我在这里反映的任何代码中。它实际上是equals / hashCode的错误实现。因为OccurrenceOfB几乎由它引用的A和B定义,所以这两个值都在equals / hashCode中引用。结果,仅仅迭代集合的行为就是触发了一次获取。因为B有一个类似的实现(引用了C),它正在执行另一个传递提取。
我完全删除了实现,并看到我的10502选择语句减少到3 - 这是我可以落后的改进。显然需要正确实现equals / hashCode(并且考虑到https://docs.jboss.org/hibernate/stable/core.old/reference/en/html/persistent-classes-equalshashcode.html中指出的警告,这将很有趣),但这超出了本文的范围。
非常感谢你的帮助和对此的想法!