我有一些代表不可变对象的类(数量,价格,概率)。有没有办法告诉Hibernate对象永远不会改变,所以它可以重用对象,而不是为每个0或1或Price = $ 1的实例创建一个新对象?
我最终创建了这些类,因为我发现双打并不能很好地表示用户输入的数字。用户输入十进制数字,如果将它们转换为双精度数,则会立即失去精度(有时也会失去正确性)。因此,我用这些基于BigDecimal的对象替换了所有数字(除了短期的int)。
在以前的几个项目中,性能优化的一个重要步骤是缓存小数字,因此每次我们引用0或1或者特定项目中常见的任何其他小数字时,我们都不会创建新对象。所以我怀疑如果hibernate知道它可以重用特定类型的对象,那么它也可以节省大量资金。
作为一个简洁的编程实践,它们是纯数字和不可变的,这意味着Java代码不必担心共享对象和副作用。我已经为我的代码中常用的数字定义了一些清单常量,但是Hibernate为它从数据库中分页的每个数字创建了一个新对象。 (怎么会这样呢?它不知道它们是不可变的,所以它不能假设它们可以被共享。)
此时我还将所有这些对象都转换为hibernate组件,因此我不必担心在数据库中查找和删除任何不再使用的数字。但这也意味着不再有Quantity.hbm.xml来放置注释,即使hibernate支持这样的注释。
顺便说一下,这次改写最令人反感的方面是所有的算术现在都显示为a.times(b), c.plus(d.minus(e))
等等。但这是一个正确性问题,所以我认为我没有选择。
答案 0 :(得分:8)
通过使用@Entity(mutable=false)
或@Immutable
注释,您可以告诉Hibernate特定的实体是不可变的。请注意,两者都是Hibernate extensions到JPA标准。
然而,不会强制Hibernate重用对象 - 就缓存/刷新而言,它只会允许一些小的性能优化。组件也不能以这种方式注释。
要做你想做的事,你必须编写自己的自定义类型;然后,您就可以为特定(最常见)值预定义实例,并返回这些实例而不是创建新实例。
另一种选择是定义PreLoadEventListener来做到这一点;但实体 已经在您的监听器被调用时实例化,因此您只能将其替换为您的实例。
答案 1 :(得分:0)
利用Hibernate二级缓存。对于您所描述的不可变对象,您将需要使用只读缓存策略。我在一些应用程序中使用了二级缓存,它带来了巨大的性能提升。值得花时间真正了解缓存的后果,所以我强烈建议您在二级缓存上阅读Hibernate文档: