将复杂项目重构为JPA或Hibernate

时间:2011-08-16 13:08:21

标签: database orm refactoring

我有足够大且已经在工作的项目,不是由程序员写的,而是由科学家编写的。该程序将大量数据保存在一个巨大的对象树中。几乎所有涉及的类都是可变的甚至更多 - 它们倾向于改变几乎所有方法中的其他对象的状态,甚至是getter和setter。这个对象树通过java序列化存储到磁盘。

我的任务是从序列化迁移到数据库,以减少内存消耗。手动重构这些可变的,在某些未知的时间点互相改变是完全地狱,特别是对我来说 - 不知道主题领域。

此类案例是否有任何方法,做法或重构模式?

1 个答案:

答案 0 :(得分:1)

我认为您已在主题栏中回答了您的问题。使用JPA或带有Annotations的Hibernate,您可以使用现有的对象模型并将每个对象类视为自己的表。不要担心开始时的约束。

在每个类中,添加一个id属性,以便可以存储它,并实现equalshashCode。 (所以你必须弄清楚是什么让一个物体等于另一个物体)。这有助于避免在数据库中创建重复项。

您需要编写代码来保留现有记录。也许访客模式在这里很合适。对于每个域对象,您添加一个方法,该方法接受访问者并调用它来持久保存该对象。

public DomainObject { 
  public DomainObject() {} 
  private int id; public int getId() { return id; } public void setId(int id) { this.id = id; }
  private OtherObject myref;
  // properties for 'myref' and other existing public fields may need to be added
  void visit(IVisitor iv) {
    // traverse object tree to hit leafs first
    myref.visit(iv); 
    // pass to other referenced objects too.
    iv.visit(this);
  }

  public boolean equals(Object alt) { return alt.id == id; }
  public int hashCode() { return id.hashCode(); }
}

public interface IVisitor { 
  public void visit(Object o);
  public void visit(DomainObject do);
}

public class PersistVisitor implements IVisitor {

  // Your favorite injection annotation, perhaps, or populate through constructor
  EntityManager em;

  public void PersistVisitor(EntityManager em) { this.em = em; }

  public void visit(Object o) {
    em.persist(o);
  }

  public void visit(DomainObject do) {
    // anything you need to do specifically for the DomainObject type
    visit((Object)o);
  }

}

在最初持久化记录之后,当您下次从Session或EntityManager加载根对象时,Hibernate将负责加载所有引用的实例。

随着时间的推移,您可以将业务逻辑移出模型类,但您不必这样做。 Hibernate将提交对对象模型中任何实例所做的任何更改,例如现有代码所做的更改。

(或者我猜你可以挂钩对象树的反序列化,以便在反序列化时保留或查找对象。我会把它作为另一个用户的练习。)