分解一个大的 Hibernate 类
-
19-09-2019 - |
题
我有一个 Hibernate 类,它本质上只是对大量集合的包装。
所以这个类(大规模简化/伪)类似于:
@Entity public class MyClass { @OneToMany Map1 @OneToMany Map2 @OneToMany Map3 AddToMap1(); AddToMap2(); AddToMap3(); RemoveFromMap1(); RemoveFromMap2(); RemoveFromMap3(); DoWhateverWithMap1(); DoWhateverWithMap2(); DoWhateverWithMap3(); }
ETC。每个映射都有一些与之关联的方法(添加/删除/询问/等)。
正如您可以想象的那样,当我添加第 10 个集合左右时,该类的大小变得有点荒谬。
我想做的是:
@Entity public class MyClass { ClassWrappingMap1; ClassWrappingMap2; ClassWrappingMap3; }
所有各种方法都包含在这些类中:
public class ClassWrappingMap1 { @OneToMany Map AddToMap(); RemoveFromMap(); DoWhateverWithMap(); }
我想也许我可以用 @Embedded
为此,但我似乎无法让它工作(Hibernate 根本不尝试将 Map 保留在wrapperClass 中)。
以前有人做过这样的事情吗?有什么提示吗?
非常感谢,
内德
解决方案
Hibernate注释手册 规定如下:
虽然 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
列)。
其他提示
虽然使用的包装类时,我不知道一个默认的策略,你可以使用Hibernate拦截器通过重写的的onLoad 方法。类似
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;
}
}
负责下列的:
使用该拦截器必须设置会话属性的客户端
所以,你的代码看起来像这样一个
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
如果您知道其他的策略,与我们分享。
的问候,