EJB3 и сохранение иерархии вручную - PullRequest
1 голос
/ 25 февраля 2009

У меня есть устаревшая база данных, которую я использую EJB3 для моделирования. База данных находится в довольно плохом состоянии, и у нас есть некоторые необычные ограничения на то, как мы вставляем в БД. Теперь я хочу смоделировать базу данных в иерархии, которая согласуется со структурой БД, но я хочу иметь возможность вручную вставлять каждую сущность по отдельности без менеджера постоянства, пытающегося сохранить потомки сущностей.

Я пытаюсь что-то вроде следующего (шаблон отсутствует):

@Entity
@Table(name = "PARENT_TABLE")
public class Parent {
    @Id
    @Column(name = "ID")
    int id;

    @OneToMany
    List<Child> children;
}


@Entity
@Table(name = "CHILD_TABLE")
public class Child {
    @Id
    @Column(name = "ID")
    int id;   
}

Теперь это исключение:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST

Теперь я знаю объект не помечен как PERSIST - я не хочу, чтобы EntityManager сохранял его! Я хочу быть в состоянии сохранить родителя сначала, а потом ребенка - но не вместе. Есть веские причины хотеть сделать это таким образом, но, похоже, не хочет играть.

1 Ответ

6 голосов
/ 25 февраля 2009

Хех, добро пожаловать в потрясающую конфигурацию JPA.

В вашем случае у вас есть два варианта:

  1. Вручную сохранить новый объект; или
  2. Автоматически сохранить его.

Чтобы автоматически сохранить его, необходимо аннотировать отношения. Это распространенная идиома один-ко-многим:

@Entity
@Table(name = "PARENT_TABLE")
public class Parent {
  @Id private Long id;

  @OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
  private Collection<Child> children;

  public void addChild(Child child) {
    if (children == null) {
      children = new ArrayList<Child>();
    }
    child.setParent(parent);
    children.add(child);
  }
}

@Entity
@Table(name = "CHILD_TABLE")
public class Child {
  @Id private Long id;

  @ManyToOne
  private Parent parent;

  public void setParent(Parnet parent) {
    this.parent = parent;
  }
}

Parent parent = // build or load parent
Child child = // build child
parent.addChild(child);

Из-за сохранения каскада это сработает.

Примечание: Вы должны сами управлять отношениями на уровне Java, следовательно, вручную устанавливая родителя. Это важно.

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

entityManager.persist(child);

В этот момент он будет работать правильно (при условии, что все остальное работает).

Для чисто дочерних сущностей я бы предпочел подход аннотации. Это просто проще.

Есть одна ошибка, которую я упомяну в JPA:

Parent parent = new Parent();
entityManager.persist(parent);
Child child = new Child();
parent.addChild(child);

Теперь я немного обеспокоен этим, но я полагаю, что у вас могут возникнуть проблемы, если вы сделаете это, потому что родитель был сохранен до добавления ребенка. Будьте внимательны и проверяйте это дело независимо от того, что вы делаете.

...