Будьте в спящем режиме аннотируемый many-one, не добавляющий ребенка для порождения Набора

У меня есть аннотируемое следующее, в спящем режиме классы объекта:

@Entity
public class Cat {
    @Column(name = "ID") @GeneratedValue(strategy = GenerationType.AUTO) @Id
    private Long id;

    @OneToMany(mappedBy = "cat", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Set kittens = new HashSet();

    public void setId(Long id) { this.id = id; }
    public Long getId() { return id; }
    public void setKittens(Set kittens) { this.kittens = kittens; }
    public Set getKittens() { return kittens; }
}

@Entity
public class Kitten {
    @Column(name = "ID") @GeneratedValue(strategy = GenerationType.AUTO) @Id
    private Long id;

    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private Cat cat;

    public void setId(Long id) { this.id = id; }
    public Long getId() { return id; }
    public void setCat(Cat cat) { this.cat = cat; }
    public Cat getCat() { return cat; }
}

Мое намерение здесь является двунаправленными one-to-many/many-to-one отношениями между CAT и Котенком, при этом Котенок является "стороной владения".

То, что я хочу произойти, - когда я создаю новый CAT, сопровождаемый новым Котенком, ссылающимся на CAT, Набор котят на моем CAT должен содержать нового Котенка. Однако этого не происходит в следующем тесте:

@Test
public void testAssociations()
{
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    Transaction tx = session.beginTransaction();

    Cat cat = new Cat();
    session.save(cat);

    Kitten kitten = new Kitten();
    kitten.setCat(cat);
    session.save(kitten);

    tx.commit();

    assertNotNull(kitten.getCat());
    assertEquals(cat.getId(), kitten.getCat().getId());
    assertTrue(cat.getKittens().size() == 1); // <-- ASSERTION FAILS
    assertEquals(kitten, new ArrayList(cat.getKittens()).get(0));
}

Даже после перезапросов CAT, Множество все еще пусто:

// added before tx.commit() and assertions
cat = (Cat)session.get(Cat.class, cat.getId());

Я ожидаю слишком много из, в спящем режиме здесь? Или нагрузка на мне для управления Набором самом? (Аннотации) документация не делает признака, что я должен создать удобство addTo*/removeFrom* методы на моем родительском объекте.

Кто-то может просветить меня на том, от чего должны быть мои ожидания, в спящем режиме с этими отношениями? Или если ничто иное, укажите на меня на корректное, в спящем режиме документация, которая говорит мне, что я должен ожидать происходить здесь.

Что я должен сделать, чтобы заставить родительский Набор автоматически содержать дочерний Объект?

7
задан Rob Hruska 27 May 2010 в 13:03
поделиться

2 ответа

Он не будет добавлять его автоматически. Вы должны добавить это сами.

Я бы также не стал напрямую вызывать Kitten.setCat () . Типичный шаблон для этого - поместить метод в Cat , например:

public void addKitten(Kitten kitten) {
  if (kittens == null) {
    kittens = new HashSet<Kitten>();
  }
  kittens.add(kitten);
  kitten.setCat(this);
}

, а затем просто вызвать:

cat.addKitten(kitten);
15
ответ дан 6 December 2019 в 10:47
поделиться

При работе с двунаправленными ассоциациями вы должны обрабатывать обе стороны «ссылки», и для этого очень часто используются методы управления защитными ссылками, как предлагает @cletus. Из документации по Hibernate Core:

1.2.6. Работа с двунаправленными ссылками

Во-первых, имейте в виду, что Hibernate не влияет на нормальную семантику Java. Как мы создали связь между Лицо и событие в однонаправленный пример? Вы добавляете экземпляр Event в коллекцию Ссылки на события экземпляра Человек. Если вы хотите сделать эту ссылку двунаправленный, вы должны сделать то же самое на другой стороне, добавив Ссылка на коллекцию в Событие. Этот процесс «настройки» ссылка с обеих сторон» необходим с двунаправленными ссылками.

Многие разработчики программирует оборонительно и создание методов управления ссылками для правильно установить обе стороны (например, in Person):

protected Set getEvents() {
 события возврата;
}

protected void setEvents(Set events) {
 this.events = события;
}

public void addToEvent(Событие события) {
 this.getEvents().add(event);
 event.getParticipants().add(this);
}

public void removeFromEvent(Событие события) {
 this.getEvents().remove(event);
 event.getParticipants().remove(this);
}

Методы get и set для коллекции теперь защищены. Этот разрешает занятия в одном пакете и подклассы для доступа к методы, но мешает всем остальным от изменения коллекций прямо. Повторите шаги для коллекция с другой стороны.

Другие ссылки

3
ответ дан 6 December 2019 в 10:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: