Прежде чем перейти к ответу:
- Да, вы правы, Hibernate в настоящее время использует Javassist (в прошлом он использовал GCLib, но он устарел) для инструментальных классов во время выполнения.
- Hibernate действительно создает подклассы во время выполнения, у которых есть прокси для постоянных сущностей.
Короткий ответ
К сожалению, я не думаю, что вы сможете настроить Hibernate для использования собственной фабрики. Для подробностей предлагаю прочитать часть с длинным ответом.
Длинный ответ
Насколько мне известно, в настоящее время Hibernate 4.x поддерживает только Javassist в качестве поставщика манипуляций с байт-кодом. Хотя раньше он позволял переключаться между GClib и Javassist в версиях 3.x. Еще в этих версиях вы могли изменить фабрику, которая будет использоваться, настроив глобальный параметр гибернации под названием hibernate.bytecode.provider
.
Этот параметр больше не отображается в документации по Hibernate 4.1, но вы все равно можете найти немного об этом в документации для Hibernate 3.2 в разделе дополнительные свойства конфигурации.
Поскольку я сам разработчик, я знаю, что иногда мы оказываемся хитрыми ребятами, и то, что что-то не в документации, не обязательно означает, что это вне кода :-) Итак, я подумал, возможно, если параметр все еще существует, мы можем попытаться использовать его, чтобы делать то, что вы хотите (хотя и не поддерживаемым способом).
Ради любопытства, поскольку на моей машине был код Hibernate 4.0.1 (заметьте, что это не последняя версия), я немного покопался ... И, к удивлению, это свойство все еще существует! После отслеживания использованных ссылок (спасибо Eclipse) я оказался в классе org.hibernate.cfg.Environment (код для версии 4.2.0.CR2), где я нашел следующий код ( код был одинаков как в моей версии, так и в 4.2.0CR2):
public static BytecodeProvider buildBytecodeProvider(Properties properties) {
String provider = ConfigurationHelper.getString( BYTECODE_PROVIDER, properties, "javassist" );
LOG.bytecodeProvider( provider );
return buildBytecodeProvider( provider );
}
private static BytecodeProvider buildBytecodeProvider(String providerName) {
if ( "javassist".equals( providerName ) ) {
return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}
LOG.unknownBytecodeProvider( providerName );
return new org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl();
}
Насколько я могу судить, это реализация Javassist для вашей прокси-фабрики, и стандартного способа ее изменить не будет.
Замечание о сумасшедшем
То, что я собираюсь сказать, является чистым безумием, и его не следует принимать во внимание в производственном коде, а только в будет ли он действительно работать / академический / позволяет изменить ситуацию .
‹Взлом молотка›
- Вы можете попробовать расширить свою собственную структуру для инструментария классов, чтобы не только добавить байт-код для ваших нужд, но также и байт-код, который нужен спящему режиму - что, я бы сказал, было бы чем-то вроде слияния ваших манипуляций с манипуляциями
org.hibernate.bytecode.internal.javassist.BytecodeProviderImpl
.
- Затем вы можете переименовать свой класс расширения в
BytecodeProviderImpl
, поместить его в тот же пакет org.hibernate.bytecode.internal.javassist
и, наконец, поместить его где-нибудь в пути к классам, где загрузчик классов найдет его перед тем, что находится в банке (или, возможно, с помощью пользовательского загрузчика классов)
Тогда вам просто понравится слушать Hibernate, ваш фреймворк и, возможно, весь JVM вопит в панике, не зная, что делать, или, может быть, это сработает ...
‹/ Взлом молотка›
В любом случае, если у вас есть время и желание попробовать, дайте мне знать, сработало ли это.
ОБНОВЛЕНИЕ
Немного поговорив в разделе комментариев, у меня возникла идея использовать пользовательский EntityPersister. Поскольку я не был очень уверен в этом, я немного погуглил, чтобы посмотреть, смогу ли я найти что-то, что могло бы сказать мне, что то, о чем я думал, сработает или нет.
Даже лучше, чем выяснять, было ли мое чутье правильным или нет, я нашел вопрос в Stackoverflow, который кажется очень похож на ваш. К сожалению, здесь нет принятого ответа.
Но первый ответ на этот вопрос дает ссылку на нечто похожее на то, о чем я думал. Цитата Паскаля Тивента:
настраиваемая реализация EntityPersister (которую можно зарегистрировать для конкретного сущность во время инициализации Hibernate с использованием настраиваемой конфигурации)
Верно, что это пример для Hibernate в Grails, но в простой Java он почти такой же:
public void registerCustomEntityPersister(Configuration configuration) {
final Iterator<PersistentClass> classesIterator = configuration.getClassMappings();
while (classesIterator.hasNext()) {
final PersistentClass persistentClass = classesIterator.next();
if (checkIfIsOneTheClassesThatMatters(persistentClass)) {
persistentClass.etEntityPersisterClass(CustomEntityPersister.class);
}
}
Несмотря на то, что это кажется выполнимым, похоже, слишком много работы, потому что реализация EntityPersister не выглядит таким тривиальным ... слишком много вещей. Вы можете попытаться расширить стандарт, который используется Hibernate (я действительно не знаю, какой именно), и попытаться переопределить метод getProxy (), чтобы вернуть один из ваших инструментальных классов.
Извините, если это все еще не место для ответа, но, к сожалению, я не эксперт по Hibernate, я просто использую его обычно из коробки, я действительно нашел ваш вопрос из-за тега javassist и нашел его довольно интересным.
Я надеюсь, что по крайней мере я дал вам информацию, которая может вам помочь.
person
pabrantes
schedule
26.03.2013