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.
There's one obstacle on the way of creating immutable entity classes with an ORM framework like Hibernate. Hibernate uses reflection to instantiate entities, it, therefore requires a default, no argument constructor. This means class fields can never be final.
You can tell Hibernate that a specific entity is immutable by using @Entity(mutable=false) or @Immutable annotations.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With