Hibernate Envers и "Javassist Enhancement failed" Исключение
Мы используем Hibernate Envers и имеем следующую ситуацию:
Класс BusinessObjectType
и класс Identity
со ссылкой на BusinessObjectType
:
@Entity
@Table( name = "ID_IDENTITY" )
@Audited
public class Identity {
@ManyToOne
@JoinColumn( name = "BO_TYPE_ID" )
@IndexColumn( name = "INDEX_BO_BO_TYPE" )
private BusinessObjectType businessObjectType;
[…]
}
Затем мы запрашиваем всю версию Identity с помощью:
AuditQuery auditQuery = auditReader.createQuery().forRevisionsOfEntity(
Identity.class,
false,
true );
auditQuery.add( AuditEntity.id().eq( dbid ) );
@SuppressWarnings( "unchecked" )
List< Object[]> history = (List< Object[]>) auditQuery.getResultList();
Если сохраненный идентификатор не имеет BusinessObjectType
(т.е. BusinessObjectType
is и был null), все работает как шарм.
Если идентификатор имел businessObjectType != null
, мы получим "Javassist Enhancement failed" Exception:
Javassist Enhancement failed: ch.ethz.id.wai.baseclasses.BusinessObjectType
Ошибка, похоже, связана с Envers, пытающейся создать экземпляр объекта BusinessObjectType, но я не вижу, что может быть проблемой (у Hibernate нет проблем с обоими объектами, если мы не используем AuditQuery).
Причиной исключения является
java.lang.InstantiationException: ch.ethz.id.wai.baseclasses.BusinessObjectType_$$_javassist_49
без трассировки стека.
Любой намек на то, что проблема может быть?
Ответы
Ответ 1
Это происходит внутри следующего класса JavassistLazyInitializer Jazassist-based ленивый прокси-сервер инициализации.
Без взгляда на полный источник сложно комментировать, но вы можете попробовать следующие варианты.
- Отключить Lazy loading для отношений @ManyToOne [ Это дизайнерское решение, поэтому следите, если оно не подходит в общем решении)
- Предоставить публичный конструктор по умолчанию для вашего объекта, который вызывает проблему [Это проще]
- отключить оптимизацию отражения, если это действительно не требуется, настроив свойство
hibernate.bytecode.use_reflection_optimizer
на false
Сообщите нам, если это поможет
Ответ 2
Чтобы получить дополнительную информацию об исключении, используйте средства отладки вашей среды IDE, чтобы установить контрольную точку исключения для java.lang.InstantiationException
, чтобы остановить выполнение, когда возникает основное исключение. Это должно показать полную трассировку стека и позволить вам проверять все переменные в стеке.
Если бы я должен был догадаться, мое первое подозрение было бы в том, что, поскольку ассоциация
BusinessObjectType
не отображается ленивым, простой спящий режим никогда не пытается создать прокси для класса. Кажется, что наоборот. Прокси-сервер - это подкласс, сгенерированный во время выполнения, переопределяя все общедоступные методы. Поэтому ни класс, ни общедоступные методы (помимо тех, которые унаследованы от Object
) не могут быть объявлены final
, и конструктор по умолчанию должен быть доступен подклассу.