Comments 24
Делал такой же изврат на Codedom + NHibernate. Из опыта уверен, что означенная проблема должна решаться как-то по другому )
+3
1) каким образом происходим изменение Типов? к примеру удаление и удаление полей на лету? интересен момент работы с Hibernate в этот момент
2) получается каждый раз при поднятии сервера, он компилит классы типов заново?
2) получается каждый раз при поднятии сервера, он компилит классы типов заново?
0
1) При изменении структуры типов нужно заново строить классы (причём — в новом класс-лоадере, разумеется). Изменить класс на лету нельзя — можно только загрузить заново.
И после этого заново строится SessionFactory / EntityManagerFactory с новыми классами.
2) Да, при поднятии сервера и при изменении конфигурации. Но не надо боятся слова «компилит» — это происходит намного быстрее чем компилирование кода в Javac. Фактически класс загружается не с диска, а из памяти, так как код не компилирует, а практически записывает байт-код в массив.
И после этого заново строится SessionFactory / EntityManagerFactory с новыми классами.
2) Да, при поднятии сервера и при изменении конфигурации. Но не надо боятся слова «компилит» — это происходит намного быстрее чем компилирование кода в Javac. Фактически класс загружается не с диска, а из памяти, так как код не компилирует, а практически записывает байт-код в массив.
0
1) > И после этого заново строится SessionFactory / EntityManagerFactory с новыми классами
это узкое место, хотя с учетом того что классы типы изменяются очень редко, это не критично
2) необязательно использовать javac, можно заюзать ToolProvider.getSystemJavaCompiler()
это узкое место, хотя с учетом того что классы типы изменяются очень редко, это не критично
2) необязательно использовать javac, можно заюзать ToolProvider.getSystemJavaCompiler()
0
2) В том то и фишка, что компилятор вообще не используется, и это не отнимает время процессора. Какой бы JavaCompiler или EclipseJavaCompiler не использовать — это будет медленно, так как надо разобрать грамматику, найти зависимые класс, сгенерировать код и т.д. А тут — фактически двоичный код пишется, разве что байт-код, а не исполняемый машинный.
0
Спасибо за интересную и исчерпывающую статью. В текущей работе я, наверное, не буду стараться добавлять универсальности. Но на будущее очень полезно. Рад, что на хабре появляются статьи по java.
+1
Можно ли обращаться к этим классам из обычных исходников? Если нет, то можно было бы использовать DynamicMap в Hibernate.
0
опишите в двух словах что даст DynamicMap? когда-то пытался его прикрутить, но чего-то не очень получилось, может примерчик скинете достойный?
0
docs.jboss.org/hibernate/core/3.3/reference/en/html/persistent-classes.html#persistent-classes-dynamicmodels
Если в 2 словах, то вместо POJO используется HashMap. Конфигурация задается в XML. Из минусов можно отметить гемор в написании бизнес логики (нет проверки имен и типов свойств на этапе компиляции).
Если в 2 словах, то вместо POJO используется HashMap. Конфигурация задается в XML. Из минусов можно отметить гемор в написании бизнес логики (нет проверки имен и типов свойств на этапе компиляции).
0
Для обращении из обычных исходников делается так:
вариант а:
— обращаемся, как и раньше, по ((TextField)object.getField(name)).getValue()
вариант б:
— создаём интерфейс:
в описании ComplexType добавляем интерфейс:
Теперь после загрузки можно кастовать объект к этому интерфейсу и использовать поля:
вариант а:
— обращаемся, как и раньше, по ((TextField)object.getField(name)).getValue()
вариант б:
— создаём интерфейс:
public interface ArticleContent { public String getContent(); public void setContent(String value); }
в описании ComplexType добавляем интерфейс:
complexType.getInterfaces().add(ArticleContent.class);
Теперь после загрузки можно кастовать объект к этому интерфейсу и использовать поля:
ArticleContent content = (ArticleContent) loaded; content.getContent();
0
Я не очень понял суть решения, но не проще ли генерировать исходные ява-файлы, а не байт-код? И да, кодогенераци в данном примере имхо изврат и неправильный подход. Кодогенерацией как правило, пользуются, чтобы автоматизировать процес создания кода методом копипаста, что изначально неправильно.
И тем более в ява кодогенерация неоправданна, так как там код загружается не при каждом запросе как в PHP апри старте сервера. Вы можете сгенерировать лббые классы динамически.
И тем более в ява кодогенерация неоправданна, так как там код загружается не при каждом запросе как в PHP апри старте сервера. Вы можете сгенерировать лббые классы динамически.
0
UFO just landed and posted this here
Нет, это не то. Генерировать классы динамически — значит создавать их в памяти, добавляя свойства и методы, а не байт код или исходный код.
0
Интересно послушать как, не добавляя байт-код или исходный-код, вы собираетесь добавлять методы. Что же они делать-то будут?
Может быть, вы имеете ввиду Proxy + interfaces + InvokationHandler, когда коду передаётся имя метода и он решает, как этот метод должен работать? Это тоже вариант, но намного более медленный.
Может быть, вы имеете ввиду Proxy + interfaces + InvokationHandler, когда коду передаётся имя метода и он решает, как этот метод должен работать? Это тоже вариант, но намного более медленный.
0
Имхо у подхода есть один существенный недостаток: хибернейт при изменении модели не умеет делать ALTER таблицы, а вместо этого делает DELETE и затем CREATE таблицы. А значит что пропадает полностью все текущее состояние.
Если ты научил хибернейт менять схему, то дай знать пожалуйста.
Если ты научил хибернейт менять схему, то дай знать пожалуйста.
0
да ну, у меня он делает ALTER при расширении полей типа, а вот при уменьшении поля таблицы остаются, нужно руками удалять
0
В общем случае этого нельзя добиться даже теоретически, так как неизвестно: переименовал ты колонку или удалил старую и добавил новую. Для того, чтобы заработало автоматическое обновление схемы нужно в некотором виде хранить историю изменений классов объектов с данными. Например, в аннотации к свойству указывать предыдущие имена.
+1
а если операции переименовывания или удаления делать через спец методы, тогда можно добится
+1
Поподробнее можно? ссылочку какую-нибудь подкиньте, пожалуйста.
0
подробнее в 2-х словах: переименование полей делаете через свой спец метод, который удалит старое поле в классе и создаст новое (после чего Хибернейт сделает ALTER) + этот же метод либо удалит старое поле в таблице, либо сначала скопирует данные в новое поле а только потом удалит старое. Вообщем это надо руками делать, но это реально реализуемо, мы сделали такой механизм у себя в сервисе структур
+1
У меня делает Alter, что я делаю не так? :)
-1
А не лучше ли, кстати, использовать groovy для динамической метамодели? Какие мысли по этому поводу? По идее значительно проще: www.jroller.com/melix/entry/dynamic_database_models_with_groovy
0
Sign up to leave a comment.
Articles
Change theme settings
Java-ассемблер, мета-программирование и JPA