Рефакторинг сложного проекта в JPA или Hibernate - PullRequest
1 голос
/ 16 августа 2011

У меня достаточно большой и уже работающий проект, написанный не программистом, а ученым.Программа хранит много данных в огромном дереве объектов.Почти все участвующие классы являются изменяемыми и даже больше - они имеют тенденцию изменять состояние других объектов почти во всех методах, даже в методах получения и установки.Это дерево объектов затем сохраняется с помощью Java-сериализации на диск.

Моя задача - перейти от сериализации к базе данных, чтобы уменьшить потребление памяти.Ручной рефакторинг этой тонны изменчивых файлов, изменение друг друга в некоторые неизвестные моменты времени - это совершенно ад, особенно для меня - не зная предметную область.

Существуют ли какие-либо подходы, практики или шаблоны рефакторинга для такихслучаи

1 Ответ

1 голос
/ 16 августа 2011

Я думаю, что вы ответили на свой вопрос в строке темы. Используя JPA или Hibernate с аннотациями, вы можете взять существующую объектную модель и рассматривать каждый класс объектов как свою собственную таблицу. Не беспокойтесь об ограничениях для начала.

В каждом классе добавьте свойство id, чтобы его можно было сохранить, и реализуйте equals и hashCode. (так что вам придется выяснить, что делает объект равным другому). Это поможет избежать создания дубликатов в вашей базе данных.

Вам нужно будет написать код, чтобы сохранить существующие записи. Возможно, здесь хорошо подойдет модель Visitor. К каждому объекту домена вы добавляете метод, который принимает посетителя и вызывает его для сохранения объекта.

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 будет фиксировать любые изменения, сделанные в любых экземпляров в объектной модели, например, сделанные существующим кодом.

(В качестве альтернативы, я думаю, вы могли бы подключиться к десериализации дерева объектов, чтобы сохранить или выполнить поиск объектов по мере их десериализации. Я оставлю это как упражнение для другого пользователя.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...