Разбиение большого класса Гибернации
-
19-09-2019 - |
Вопрос
У меня есть класс Hibernate, который по сути является просто оболочкой для множества коллекций.
Таким образом, класс представляет собой (сильно упрощенный / псевдо) что-то вроде:
@Entity public class MyClass { @OneToMany Map1 @OneToMany Map2 @OneToMany Map3 AddToMap1(); AddToMap2(); AddToMap3(); RemoveFromMap1(); RemoveFromMap2(); RemoveFromMap3(); DoWhateverWithMap1(); DoWhateverWithMap2(); DoWhateverWithMap3(); }
и т.д.Затем каждая из этих карт имеет несколько методов, связанных с ней (добавление / удаление / опрос / и т.д.).
Как вы можете себе представить, к тому времени, когда я добавил 10-ю коллекцию или около того, класс стал немного смехотворного размера.
То, что я хотел бы сделать, это что-то вроде:
@Entity public class MyClass { ClassWrappingMap1; ClassWrappingMap2; ClassWrappingMap3; }
Со всеми различными методами, включенными в эти классы:
public class ClassWrappingMap1 { @OneToMany Map AddToMap(); RemoveFromMap(); DoWhateverWithMap(); }
Я подумал, что, возможно, я мог бы использовать @Embedded
для этого, но я, похоже, не могу заставить его работать (Hibernate просто даже не пытается сохранить Map внутри wrapperClass).
Кто-нибудь когда-нибудь делал что-то подобное раньше?Какие-нибудь намеки?
Большое спасибо,
Нед
Решение
Руководство по переходу в спящий режим для аннотаций государства , следующие:
Несмотря на то, что спецификация EJB3 не поддерживает Hibernate Annotations, она позволяет использовать аннотации ассоциаций в встраиваемом объекте (например, @*ToOne или @*ToMany).Чтобы переопределить ассоциативные столбцы, вы можете использовать @AssociationOverride.
Таким образом, ваш подход к упаковке должен сработать.
Прежде всего, вы должны проверить все файлы журналов и т.д. На наличие любых связанных с ними ошибок.
Вы могли бы попробовать что-то вроде этого:
- В вашем мастер - классе (MyClass )
@Entity public class MyClass { @Embedded ClassWrappingMap1 map1; }
- И в вашем классе упаковки
@Embeddable public class ClassWrappingMap1 { @OneToMany Map map1; }
Обратите внимание , что ClassWrappingMap1
использование @Embeddable
аннотация.Однако, согласно документам, аннотация @Embeddable не должна быть необходима, она должна быть установлена по умолчанию при использовании аннотации @Embedded .
Убедитесь, что каждый класс ClassWrappingMap сопоставляет разные столбцы в базе данных.Также классы ClassWrappingMap не должны иметь первичного ключа (@Id
или @EmbeddedId
столбцы).
Другие советы
Хотя я не знаю стратегии по умолчанию при использовании класса-оболочки, вы могли бы использовать перехватчик гибернации для инициализации вашей оболочки путем переопределения Загрузка способ.Что - то вроде
public class WrapperInterceptor extends EmptyInterceptor {
private Session session;
public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
if (entity instanceof MyClass) {
MyClass myClass = (MyClass) entity;
Query query = session.createQuery(<QUERY_TO_RETRIEVE_WRAPPED_ENTITY_GOES_HERE>);
WrappedEntity wrappedEntity = query.list().get(0);
myClass.setWrapperClass(new WrapperClass(wrappedEntity));
}
}
public void setSession(Session session) {
this.session = session;
}
}
Заботится о следующем:
Клиент, использующий этот перехватчик, должен установить свойство Session
Итак, ваш код выглядит следующим образом
WrapperInterceptor interceptor = new WrapperInterceptor();
Session session = sessionFactory().openSession(interceptor);
Transaction tx = session.beginTransaction();
interceptor.setSession(session);
MyClass myClass = (MyClass) session.get(newItem, myClassId); // Triggers onLoad event
tx.commit();
session.close();
Или используйте Spring AOP для выполнения той же задачи.Видишь Дизайн, ориентированный на домен, с использованием Spring и Hibernate
Если вы знаете другую стратегию, поделитесь ею с нами.
с уважением,