Проблемы с сохранением гибернации с Bean Mapping (Dozer) - PullRequest
4 голосов
/ 29 декабря 2010

Я использую Hibernate 3, и у меня возникает особая проблема при сохранении нового объекта, который связан с существующим отдельным объектом.Самый простой способ объяснить это с помощью примеров кода.У меня есть две сущности, FooEntity и BarEntity, из которых BarEntity может быть связан со многими FooEntity:

@Entity
public class FooEntity implements Foo{

    @Id
    private Long id;

    @ManyToOne(targetEntity = BarEntity.class)
    @JoinColumn(name = "bar_id", referencedColumnName = "id")
    @Cascade(value={CascadeType.ALL})
    private Bar bar;    

}

@Entity
public class BarEntity implements Bar{

    @Id
    private Long id;

    @OneToMany(mappedBy = "bar", targetEntity = FooEntity.class)
    private Set<Foo> foos;
}

Foo и Bar являются интерфейсами, которые свободно определяют геттеры для различных полей.Существуют соответствующие классы FooImpl и BarImpl, которые по сути являются просто объектами сущности без аннотаций.

Я пытаюсь создать новый экземпляр FooImpl и сохранить его после установки нескольких полей.В новом экземпляре Foo его член 'bar' будет установлен на существующий Bar (среда выполнения - BarEntity) из базы данных (получена с помощью session.get (..)).После того, как FooImpl установит все свои свойства, Apache Dozer используется для сопоставления между объектом 'domain' FooImpl и Entity FooEntity.Dozer делает в фоновом режиме создание нового FooEntity и установку всех соответствующих полей.BarEntity также клонируется с помощью инстанцирования и устанавливает член 'bar' в FooEntity.

После этого, передавая новый объект FooEntity для сохранения.Это выдает исключение:

org.hibernate.PersistentObjectException: detached entity passed to persist: com.company.entity.BarEntity

Ниже приведен код, который выполняет шаги

FooImpl foo = new FooImpl();
//returns at runtime a persistent BarEntity through session.get()
Bar bar = BarService.getBar(1L);
foo.setBar(bar);

...

//This constructs a new instance of FooEntity, with a member 'bar' which itself is a new instance that is detached)
FooEntity entityToPersist = dozerMapper.map(foo, FooEntity.class);

...

session.persist(entityToPersist);

Мне удалось решить эту проблему, удалив или изменив аннотацию @Cascade,но это ограничивает будущее использование, скажем, добавления нового Foo с уже прикрепленным новым Bar.Есть ли какое-то решение здесь, которого я пропускаю?Я был бы удивлен, если бы эта проблема не была решена где-то прежде, либо путем изменения того, как Dozer Maps отображает дочерние элементы Foo, либо как Hibernate реагирует на отдельную дочернюю сущность.

Ответы [ 2 ]

0 голосов
/ 03 февраля 2011

Я подозреваю, что виновата картография Дозера.Попробуйте добавить атрибут copy-by-reference = "true" в панель свойств FooImpl / FooEntity.

0 голосов
/ 04 января 2011

Не могли бы вы посмотреть, есть ли у вас транзакция обернута вокруг этого? Если транзакция не обернута вокруг второго отправленного вами кода, то BarEntity будет отсоединен от сеанса Hibernate к тому времени, когда вы попытаетесь сохранить его, что приведет к указанной вами ошибке.

...