Я нашел решение отменить класс, используя стандартные API Java и JPA. Протестировано с hibernate, но не требует hibernate в качестве зависимости и должно работать со всеми поставщиками JPA.
Единственное требование - необходимо изменить родительский класс (Address) и добавить простой вспомогательный метод.
Общая идея: добавить вспомогательный метод в родительский класс, который возвращает сам себя. когда метод вызывается через прокси, он переадресует вызов реальному экземпляру и возвращает этот реальный экземпляр.
Реализация немного сложнее, поскольку hibernate распознает, что прокси-класс возвращает себя и по-прежнему возвращает прокси вместо реального экземпляра. Обходной путь - обернуть возвращаемый экземпляр в простой класс-оболочку, тип класса которого отличается от реального экземпляра.
В коде:
class Address {
public AddressWrapper getWrappedSelf() {
return new AddressWrapper(this);
}
...
}
class AddressWrapper {
private Address wrappedAddress;
...
}
Чтобы привести Address proxy к реальному подклассу, используйте следующее:
Address address = dao.getSomeAddress(...);
Address deproxiedAddress = address.getWrappedSelf().getWrappedAddress();
if (deproxiedAddress instanceof WorkAddress) {
WorkAddress workAddress = (WorkAddress)deproxiedAddress;
}