我有一个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中)。
以前有没有人做过这样的事情?任何提示?
非常感谢,
奈德
答案 0 :(得分:2)
Hibernate manual for annotations 状态如下:
虽然EJB3规范不支持,但Hibernate Annotations允许您在可嵌入对象中使用关联注释(即@ * ToOne或@ * ToMany)。要覆盖关联列,可以使用@AssociationOverride。
所以你的包装方法应该有用。
首先,您应检查所有日志文件等是否存在任何相关错误。
您可以尝试这样的事情:
@Entity public class MyClass { @Embedded ClassWrappingMap1 map1; }
@Embeddable public class ClassWrappingMap1 { @OneToMany Map map1; }
请注意ClassWrappingMap1
使用@Embeddable
注释。但是,根据文档,不应该使用@Embeddable注释,当使用@Embedded注释时它应该是默认的。
确保每个ClassWrappingMap类都映射数据库中的不同列。 ClassWrappingMap类也不应该有主键(@Id
或@EmbeddedId
列)。
答案 1 :(得分:0)
虽然我在使用包装器类时不知道默认策略,但您可以使用Hibernate Interceptor通过重写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执行相同的任务。见Domain Driven Design with Spring and Hibernate
如果您了解其他策略,请与我们分享。
的问候,