我可以告诉 Hibernate 一个类是不可变的,这样它将共享对象以节省构建成本吗?
我有一些代表不可变对象的类(数量、价格、概率)。有没有什么方法可以告诉 Hibernate 对象永远不会改变,这样它就可以重用对象,而不是为每个 0 或 1 或 Price= $1 的实例创建一个新对象?
我最终创建了这些类,因为我发现双精度数不能很好地表示用户输入的数字。用户以十进制形式输入数字,如果将它们转换为双精度数,则会立即失去精度(有时甚至是正确性)。因此,我用这些基于 BigDecimal 的对象替换了所有数字(除了短命整数)。
在之前的几个项目中,性能优化的一个主要步骤是缓存小数字,因此我们不会在每次引用 0 或 1 或特定项目中常见的任何其他小数字时创建一个新对象。因此,我怀疑如果 hibernate 知道它可以重用特定类型的对象,它也会节省大量成本。
作为干净的编程实践,它们是纯数字且不可变的,这意味着 Java 代码不必担心共享对象和副作用。我为代码中常用的数字定义了一些清单常量,但 Hibernate 为从数据库调入的每个数字创建了一个新对象。 (否则它怎么能做呢?它不知道它们是不可变的,所以它不能假设它们可以共享。)
此时我也将所有这些对象变成了休眠组件,所以我没有担心在数据库中查找和删除不再被任何东西使用的数字。但这也意味着不再有 Quantity.hbm.xml 可以添加注释,即使 hibernate 支持这样的注释。
顺便说一句,这次重写最令人反感的方面是所有算术现在都显示为 a.times(b)、c.plus(d.minus(e)) 等。但这是一个正确性问题最重要的是,所以我认为我别无选择。
I have some classes that represent immutable objects (Quantity, Price, Probability). Is there some way to tell Hibernate that the objects will never change so it can re-use objects rather than creating a new object for every instance of 0 or 1 or Price= $1?
I ended up creating these classes because I discovered that doubles don't do a good job of representing numbers typed by users. Users type numbers in decimal, and if you convert them to doubles, you immediately lose precision (and sometimes correctness). I therefore have replaced all the numbers (other than short-lived ints) with these objects which are based on BigDecimal.
In several previous projects, a major step in performance optimization was caching small numbers, so we weren't creating a new object every time we referred to 0 or 1 or whatever other small numbers were common in the particular project. So I suspect that hibernate would also make sizable savings if it knew it could re-use objects of particular types.
As a matter of clean programming practice, they are pure numbers and immutable, which means the Java code doesn't have to worry about shared objects and side effects. I've defined a few manifest constants for the numbers that are very commonly used in my code, but Hibernate creates a new object for every number it pages in from the DB. (How could it do otherwise? It doesn't know they're immutable, so it can't assume they can be shared.)
At this point I've also turned all these objects into hibernate components, so I don't have to worry about finding and deleting numbers in the database that are no longer used by anything. But that also means there's no longer a Quantity.hbm.xml to put an annotation on, even if hibernate supported such an annotation.
BTW, the most objectionable aspect of this rewrite is that all arithmetic now appears as a.times(b), c.plus(d.minus(e))
, etc. But it was a correctness issue more than anything, so I didn't think I had a choice.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用
@Entity(mutable=false)
或@Immutable
注解告诉 Hibernate 特定的实体是不可变的。请注意,两者都是 Hibernate 扩展< /a> 符合 JPA 标准。然而,这不会强制 Hibernate 重新使用这些对象——就缓存/刷新而言,它只会允许一些小的性能优化。组件也不能以这种方式注释。
要执行您想要的操作,您必须编写自己的自定义类型;然后,您将能够为特定(最常见)值预定义实例并返回这些实例,而不是创建新实例。
另一种选择是定义一个 PreLoadEventListener这样做;但是,在调用侦听器时,实体已已实例化,因此您只能将其替换为您的实例。
You can tell Hibernate that a specific entity is immutable by using
@Entity(mutable=false)
or@Immutable
annotations. Note that both are Hibernate extensions to JPA standard.That would not, however, force Hibernate to re-use the objects - it would merely allow for some minor performance optimizations as far as caching / flushing is concerned. Components can't be annotated this way either.
To do what you want you'd have to write your own custom type; you would then be able to have predefined instances for specific (most common) values and return those instead of creating a new instance.
Another alternative is to define a PreLoadEventListener to do that; however entity is already instantiated by the time your listener is called so you'd only be able to replace it with your instance.
利用 Hibernate 二级缓存。对于像您所描述的那样的不可变对象,您将需要使用只读缓存策略。我在一些应用程序中使用了二级缓存,它取得了巨大的性能改进。花时间真正理解缓存的后果是值得的,所以我强烈建议您阅读有关二级缓存的 Hibernate 文档:
Hibernate二级缓存
Take advantage of the Hibernate second level cache. For immutable objects like the ones you described you will want to use the read-only cache strategy. I've used the second level cache in a few applications and it made a huge performance improvement. It is worth spending the time to truly understand the ramifications of caching so I highly recommend you read the Hibernate docs on the second level cache:
Hibernate Second level cache