Hibernate, peristent и detached поля в transient объекте
От: manenkov  
Дата: 26.02.08 10:34
Оценка:
Добрый день.

Имеется такая струкрура классов (упрощенно):


class Order{
...
long id; 
Importer importer1;
Importer importer2;


...
}

class Importer{
long id;
...
}



маппинг Order`а:
<hibernate-mapping package="xxx.yyy">
    <joined-subclass           
        name="Order"
        table="ORDER1"
        extends="AbstractNamedEntity">
        <key column="ORDER_ID"/>
                
        <many-to-one
            name="importer1"
            class="Importer"
            cascade="save-update, replicate"
            column="IMPORTER_ID"
            lazy="false"
            />

         <many-to-one
            name="importer2"
            class="Importer"
            cascade="save-update, replicate"
            column="IMPORTER_ID"
            lazy="false"
            />
    </joined-subclass>
</hibernate-mapping>


Importer тоже замапплен в кибернейте.

То есть — имеется объект Order, объект Importer, объект Order содержит 2 поля типа Importer.


В процессе выполнения программы (веб — система) возникает такая последовательность действий (это кусок из юнит-теста):

Order o = new Order("1", "paletteLgn1", "container1", "customerLgn1", "descriptonLgn1");

Session session = HibernateUtil.getSession();
Importer imp = new Importer("importer1");
session.save(imp);
long impId = imp.getId();

HibernateUtil.closeSession();
session = HibernateUtil.getSession();

Importer imp2 = session.get(impId);
o.setImporter1(imp2);

imp2 = session.get(impId);
o.setImporter2(imp2);

HibernateUtil.closeSession();
session = HibernateUtil.getSession();

imp2 = session.get(impId);
o.setImporter1(imp2);

session.save(o);


-создали новый объект Order через new (просто как объект, пока он не в кибернейте)
-получили id персистентного объекта Importer
-закрыли/открыли сессию кибернейта
-достали из кибернейта по id персистентный объект Importer
-установили его в поле importer1 объекта Order
-установили его в поле importer2 объекта Order
-закрыли/открыли сессию кибернейта
-установили его в поле importer2 объекта Order (так получается из-за особенностей жизненного цикла бинов страниц)
-сохранили объект Order в кибернейт

Получаем ошибку
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [xxx.yyy.Importer#1364]


Насколько я понимаю, получается такая ситуация:
-перед сохранением объекта Order у него в поле importer1 находится detached объект Importer, а в поле importer2 находится persistent ТОТ ЖЕ САМЫЙ объект Importer.

Как заставить save нормально съедать такую структуру? Я так понимаю, это настройки маппинга объекта Order, а именно связи с Importer, (cascade, но какое именно нужно значение или значения?)


Спасибо.
Re: Hibernate, peristent и detached поля в transient объекте
От: Blazkowicz Россия  
Дата: 26.02.08 10:43
Оценка:
Здравствуйте, manenkov, Вы писали:

M>Получаем ошибку

M>org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [xxx.yyy.Importer#1364]
M>Насколько я понимаю, получается такая ситуация:
M>-перед сохранением объекта Order у него в поле importer1 находится detached объект Importer, а в поле importer2 находится persistent ТОТ ЖЕ САМЫЙ объект Importer.

session.merge()?
Re[2]: Hibernate, peristent и detached поля в transient объе
От: manenkov  
Дата: 26.02.08 12:59
Оценка:
Здравствуйте, Blazkowicz, Вы писали:
B>session.merge()?

merge, судя по документации, предназначен для сохранения объекта с id, уже присутствующим в базе. А в нашем случае объект Order перед сохранением к базе еще отношения не имеет (является transient).
Проблема решилась использованием Session.repicate, но не совсем понимаю почему это работает, ведь replicate должен работать с detached объектом, а не transient.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.