Ok, there are some ways around this. Admittedly, they are BAD! (Shame on me for even inventing them!) They pretty much violate basic tenets of Object Oriented Programming. The Hibernate authors will probably yank my Swanky Programmers Club membership card for even disclosing these workarounds.
Oh well.
For starts, it's often valuable to iterate a collection of heterogenous objects and perform disparate operations on them that are not permitted by their common ancestor. In other words, you want to do crazy things that break encapsulation. A great way to do that is the Visitor pattern, as described in my writeup:
http://www.hibernate.org/280.html
The Visitor pattern also happens to punch past the proxy objects nicely. You can even use it to "visit" single objects. Combined with anonymous inner types, you can get into all kinds of trouble. The only down side is that it is much more verbose, although more object oriented than the stricnine/cyanide combo of typecast/instanceof. If that isn't enough for you and you still want to typecast your little heart out, you can use the following "hack."
All my Hibernate model objects descend from a base object. To this object I add three utility hack methods to punch past the proxy layer for type info purposes:
Code:
public class BaseModel {
// all your id stuff goes here...
. . .
public boolean isInstance(Class clazz) {
return this.getClass().isAssignableFrom(clazz);
}
public BaseModel unproxy() {
return this;
}
public BaseModel unproxyIfInstance(Class clazz) {
return isInstance(clazz) ? this : null;
}
}
The first method can be used in place of instanceof. The second allows you to remove the proxy. The third method conveniently combines the first two, since in places like UI code you often use both of them together.
Because these methods are on the base class, the proxy mechanism will implement them. They will safely delegate the method calls back to the underlying object:
Code:
public Class A extends BaseModel {}
public Class B extends BaseModel {}
... // somewhere, later in your non-OO codebase...
BaseModel model = someService().getModel(id);
if (model.isInstance(A.class) {
A a = (A)model.deproxy();
} else if (model.isInstance(B.class) {
B b = (B)model.deproxy();
}
B b = (B)model.deproxyIfInstance(B.class);
if (b is null) // do something
Pretty frigtening, eh? What have I done...