打破一个大的Hibernate类

时间:2009-12-12 10:16:19

标签: hibernate wrapper hibernate-mapping

我有一个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中)。

以前有没有人做过这样的事情?任何提示?

非常感谢,
奈德

2 个答案:

答案 0 :(得分:2)

Hibernate manual for annotations 状态如下:

  

虽然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列)。

答案 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

如果您了解其他策略,请与我们分享。

的问候,