我的模型中有一个集合,其中包含一组根域对象的“以前版本”。因此,以前的版本是“不可变的”,我们永远不想更新它们,只想在它们出现时添加过去的版本。此外,“版本化”域对象相当复杂,并导致检索大量数据库访问。
当我有这些对象之一的新版本时,我希望将其与其他对象一起保存,而不加载整个集合。高级常见问题解答对此提供了一些建议:
当我只想添加或删除一个元素时,为什么Hibernate总是初始化一个集合?
不幸的是,集合API定义的方法返回值只能通过命中数据库来计算。有三种例外情况:Hibernate可以添加到用inverse="true"
声明的<bag>
、<idbag>
或<list>
,而无需初始化集合;返回值必须始终为真。
如果要避免额外的数据库流量(即在性能关键代码中),重构模型以仅使用多对一关联。这几乎总是有可能的。然后使用查询来代替集合访问。
我对所有这些都是新的,并不是100%确定如何重构您的模型,以便只使用多对一的关联。任何人都可以请给予我一个例子,为我指出一个教程,使我可以了解这将如何解决我的问题?
5条答案
按热度按时间oyt4ldly1#
当你有一个基于List或Set的集合,并且你向集合中添加了一个新对象时,Hibernate总是会命中数据库,因为它在保存或更新之前使用equals实现逐个比较对象-当使用Set时-或者当使用List时通过比较索引列。由于Set和List语义,需要此行为。正因为如此,无论您是否有一堆记录,应用程序的性能都会显著降低。
解决此问题的一些变通方法
1º通过使用封装的Bag集合加上所需的Set或List作为属性显示的转换模式
字符串
2º使用多对一而不是一对多
型
3º缓存-应用时,根据您的要求,您的配置可能会提高或降低应用程序的性能。看这里
4°SQL约束-如果您想要一个行为像Set的集合,您可以使用SQL约束,它可以应用于一列或 * 列集 *。参见here
ha5z0ras2#
我通常这样做的方式是将集合定义为“逆”。
这大致意味着:1-N关联的主要定义在“N”端完成。如果您想向集合中添加某些内容,则需要更改详细数据的关联对象。
一个小的XML示例:
字符串
则只在地址:
型
成交,你甚至都没碰那些藏品将其视为只读,这对于使用HQL进行查询、迭代和显示可能非常实用。
erhoui1w3#
我曾经为这种情况创建了一个原生查询,如下所示:
字符串
它非常快,因为不需要加载集合。
hgtggwj04#
如果我理解你的需求:
您是否考虑过保持收藏断开连接?
bejyjqdl5#
这将最小化所选数据
@LazyCollection(LazyCollectionOption.EXTRA)
但是在foreach迭代这个集合时要小心N+1个问题。