将复杂项目重构为 JPA 或 Hibernate

发布于 2024-11-30 02:52:42 字数 257 浏览 0 评论 0原文

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

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

对于此类情况是否有任何方法、实践或重构模式?

I have big enough and already working project, written not by a programmer, but a scientist. The program holds lot of data in a huge object tree. Almost all of the classes involved are mutable and even more -- they tend to change state of other objects in almost all methods, even getters and setters. This object tree is than stored via java serialization to disk.

My task is to migrate from serialization to database, to reduce memory consumption. Manual refactoring of this tons of mutables, changing each other at some unknown points in time is completely hell, especially for me -- not knowing the subject domain.

Are there any approaches, practices, or refactoring patterns for such cases?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

今天小雨转甜 2024-12-07 02:52:42

我认为您已经在主题行中回答了您的问题。使用带有注释的 JPA 或 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 将提交对对象模型中的任何实例所做的任何更改,例如现有代码所做的更改。

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

I think you have answered your question in the subject line. Using JPA or Hibernate with Annotations, you can take the existing object model and treat each object class as it's own table. Don't worry about constraints to start with.

In every class, add an id property, so that it can be stored, and implement equals and hashCode. (so you'll have to figure out what makes an object equal to another). This will help avoid the creation of duplicates in your database.

You will need to write code to persist your existing records. Perhaps the Visitor pattern would be a good fit here. To each domain object you add a method which takes a visitor and invokes it to persist the object.

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);
  }

}

After the initial persisting of the records, when you next load in your root object from Session or EntityManager, Hibernate will take care of loading all the referenced instances.

Over time, you can move business logic out of the model classes, but you won't have to do this to start with. Hibernate will commit any changes made to any of the instances in the object model, such as those made by the existing code.

(Alternatively I guess you could hook into the deserialization of the object tree in order to persist or lookup the objects as they are deserialized. I'll leave that as an exercise for another user.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文