отображение аннотаций двунаправленное OneToMany / ManyToOne не загружается? - PullRequest
6 голосов
/ 11 мая 2011

Я явно изо всех сил пытаюсь понять это, поэтому помощь очень ценится ...

У меня есть следующее отображение:

@Entity
@Table(name = "parent")
public class ParentEntity
{
...
    @Id
    @Column(name = "parent_id")
    private Long id;
...
    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
    private List<ChildEntity> children;
...
}

@Entity
@Table(name = "child")
public class ChildEntity
{
...
    @Id
    @Column(name = "child_id")
    private Long id;
...
    @ManyToOne(fetch = FetchType.EAGER)
    @NotFound(action = NotFoundAction.IGNORE)
    @JoinColumn(name = "parent_id")
    private ParentEntity parent;
...
}

в моем БД у меня есть:

parent
------
parent_id: 1

child
------
child_id: 1, parent_id: 1

Однако

((Parent) session.get(Parent.class, 1)).getChildren()

возвращает ноль.

Кто-нибудь может увидеть, что мне не хватает?

спасибо, с.

РЕДАКТИРОВАТЬ

Похоже, что более важно сделать с состоянием сеанса в том, что коллекция не заполняется в контексте того же сеанса, но коллекция заполняется в следующем сеансе ...

Примите во внимание следующее:

void setupRender()
{
    debug("existing not just added", (ParentEntity) session.get(ParentEntity.class, 13L));

    ParentEntity parent = new ParentEntity();
    session.save(parent);

    ChildEntity child = new ChildEntity();
    child.setParent(parent);
    session.save(child);

    debug("new one before commit", parent);

    sessionManager.commit();

    debug("new one after commit", parent);

    debug("new one after re-fetch", (ParentEntity) session.load(ParentEntity.class, parent.getId()));
}

private void debug(String prefix, ParentEntity parent)
{
    log.debug(prefix + ": parent id: " + parent.getId() + ", Children is "
            + (parent.getChildren() == null ? "null" : "size:" + parent.getChildren().size()));
}

приводит к следующему выводу:

DEBUG - existing not just added: parent id: 13, Children is size:1
DEBUG - new one before commit: parent id: 23, Children is null
DEBUG - new one after commit: parent id: 23, Children is null
DEBUG - new one after re-fetch: parent id: 23, Children is null

, поэтому, если это связано с состоянием сеанса, и фиксации недостаточно для запускаre-fetch, что мне нужно сделать, чтобы получить сопоставление для извлечения коллекции?

еще раз спасибо!

Ответы [ 4 ]

2 голосов
/ 11 мая 2011

Да, фиксация не запускает обновление кэша сеанса.

Типичный подход здесь - использовать шаблон сеанса для запроса, чтобы вы закрывали сеанс сразу после принятия и открывали другой сеанс для следующих транзакций (хотя это не вариант, если вы используете Открыть сеанс в Посмотреть шаблон ).

Еще одна хорошая практика, которая может помочь решить эту проблему, - это изменить обе стороны двунаправленных отношений одновременно:

public class ParentEntity {
    ...
    public void addChild(ChildEntity c) {
        children.add(c);
        c.setParent(this);
    }
}

Таким образом, вы можете поддерживать объекты в кэше сеанса в согласованном состоянии.

Наконец, если вам действительно нужно обновить объект внутри сеанса, вы можете вызвать Session.refresh() для него.

1 голос
/ 11 мая 2011

Добавление каскадного атрибута как части вашего OneToMany в родительский объект может решить проблему.

@Entity
@Table(name = "parent")
public class ParentEntity
{
...
    @Id
    @Column(name = "parent_id")
    private Long id;
...
    @OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade=CascadeType.ALL)
    private List<ChildEntity> children;
...
}

Затем, чтобы сохранить строку

ParentEntity parent = new ParentEntity();

ChildEntity child = new ChildEntity();
child.setParent(parent);
parent.getChildren().add(child);
session.save(parent);

При удалении родителя также будут удалены все дочерние элементы.

0 голосов
/ 18 августа 2011

Решение, которое я использую в данный момент , состоит в том, чтобы инициализировать коллекцию вручную во время построения:

private List<ChildEntity> children 
    = new ArrayList<ChildEntity>;

Я не уверен, что это хорошая практика, но она работает и проста.

0 голосов
/ 11 мая 2011

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

Кстати, вот официальное руководство по этой теме: (взято из http://community.jboss.org/wiki/HibernateFAQ-CommonProblems)

У меня проблемы с двунаправленной ассоциацией.

При обновлении двунаправленной ассоциации вы должны обновить оба конца.

parent.getChildren().add(child);
child.setParent(parent);

Лучше всего это сделать в методе управления ассоциациями вашего постоянного класса.

У меня все еще проблемы!

Прочитайте документацию! В главе 16 справочной документации есть подробный раздел об отношениях между родителями и детьми, включая примеры кода.

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