Mapping Hibernate "Custom" Subclasses
As a new Hibernate user, I have heard that a good pattern for adding some helper methods to generated classes is to add them in a subclass. For example:
// generated via Hibernate mapping file
public class GeneratedClass {
long id;
String someValue;
// etc, etc.
}
// my own class with pretty printing method
public class MyGeneratedClass extends GeneratedClass {
public String prettyPrint() {
return "an object: " + id + "," + someValue;
}
}
What I would like to be able to do is the following: have Hibernate return objects of type MyGeneratedClass instead of GeneratedClass so that I can work with the subclass directly. Can the mapping file be defined in this way (i.e. without the generation overwriting any custom code)?
For any possible solution, if GeneratedClass is part of a class hierarchy (i.e. GeneratedClassTypeA, GeneratedClassTypeB both which extend GeneratedClass), would this pattern still work?
I suppose an alternative would be to create a static factory method to create MyGeneratedClass from GeneratedClass, but this seems inefficient for a large number of objects.
Thanks in advance!
EDIT
After trying out the union-class strategy, I realized it did not work in my situation because of the existing class hierarchy and data. Also, I could not control the generation from overwriting my subclass (a desirable feature in hbm2java maybe?). Finally, I did consider embedding code inside mapping file, but overriding things like getters and setters looked pretty tedious.
I reviewed the approach and decided to go with annotating the domain objects and avoid using hbm2java entirely. It's not entirely ideal (the mapp开发者_StackOverflow社区ing seemed easier to deal with), but from what I have gathered from various sources, it might be the most appropriate way to deal with my particular situation because it gives me the freedom to customize the code with type checking and deal with only the class file.
I'd welcome any other thoughts or comments on my solution.
EDIT 2
The solution proposed below, using
<meta attribute="generated-class">CountryBase</meta>
is a good solution to the original problem which was described originally. However, what I discovered was that having object hierarchies and using superclass methods does not work as well with this solution, in which case annotations seems to be a better bet.
What I would like to be able to do is the following: have Hibernate return objects of type MyGeneratedClass instead of GeneratedClass so that I can work with the subclass directly. Can the mapping file be defined in this way?
Yes, you just need to specify your subclass in the mapping: <class name="Subclass" table="table">
. Then you use Subclass.class
to query the entities.
For any possible solution, if GeneratedClass is part of a class hierarchy (i.e. GeneratedClassTypeA, GeneratedClassTypeB both which extend GeneratedClass), would this pattern still work?
Yes. As long as the properties defined in the mapping exist in the class (be it because of inheritence), it should work.
I suppose an alternative would be to create a static factory method to create MyGeneratedClass from GeneratedClass, but this seems inefficient for a large number of objects.
Indeed.
EDIT
I didn't understood from your question that you generated the class out of the mapping. I thought it was generated from some other model that would spit the mapping and the class. Your comment clarified this. I would then try an approach using hibernate inheritance:
<class name="GeneratedClass" abstract="true">
<id name="id" type="long" column="XXX">
<generator class="sequence"/>
</id>
<property name="zzzz" column="ZZZZ"/>
...
<union-subclass name="SubClass" table="TABLE">
</union-subclass>
</class>
I didn't tested the snippet above, but I'm fairly convinced that your scenario can be mapped one way or the other. The abstract=true
is maybe superfluous, but it shows the fact that the parent superclass should not be instanciated. The subclass has no additional property so the subclass
tag is empty.
EDIT 2
Did you also try with <meta attribute="generated-class">CountryBase</meta>
? Never used it but it seems to fit this purpose. See "Using a Base Class" in Hibernate Class Generation with hbm2java
精彩评论