Hibernate: обновление объекта -> также выполняются нежелательные операторы удаления - PullRequest
2 голосов
/ 15 декабря 2010

Я использую Hibernate в качестве ORM в своем приложении Java. У меня есть много человек-отношение Project <-> Person, и Project является владельцем картографии.

Теперь у меня проблема, что я хочу обновить проект. У проекта есть идентификатор, имя, ... и набор людей. При обновлении все лица удаляются из таблицы присоединения Project_Person, а операторы SQL на консоли:

Hibernate: update Project set description=?, name=? where id=?
Hibernate: delete from Project_Person where project_id=?

Но я не хочу, чтобы оператор delete выполнялся.

У меня есть это в моем приложении Java:

this.projService.updateProject(p);

, где p - Проект, но в стиле POJO без Множества Людей. Поэтому я подумал, чтобы сделать его «готовым к гибернации», я делаю это в отдельной транзакции findProjectById, поэтому я выбираю проект из базы данных:

Project proj = this.projService.findProjectById(p.getId());
proj.setName(p.getName());
proj.setDescription(p.getDescription());

Итак, я получаю готовый к Hibernate объект Project, изменяю значения и затем говорю ему обновить проект. Но набор находится в представлении отладчика как PersistentSet, и в нем нет людей (я думаю, потому что они загружены лениво). Но обновление с

session.update(p);

в новой транзакции я получаю оператор обновления и нежелательный оператор удаления. Как я могу избежать оператора удаления?

Нужно ли создавать специальный оператор SQL, чтобы обновлялись только те поля таблицы базы данных, которые я хочу обновить? Или есть другие / лучшие решения?

С наилучшими пожеланиями.


Обновление Это создает исключение LazyInitializationException:

public Project findProjectById(int projectId) {
    SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    Session sess = sessionFactory.getCurrentSession();
    Transaction tx = sess.beginTransaction();
    try {
        Project project = (Project)sess.createQuery("from Project where id = "+projectId).list().get(0);
        tx.commit();
        System.out.println(project.getPersons().size());
        return project;
    } catch (IndexOutOfBoundsException ex) {
        return null;
    }
}

Снимок экрана отладчика :

http://img94.imageshack.us/img94/2020/screendebugger.png

HibernateUtil

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {
    // SessionFactory of Hibernate
    private static final SessionFactory sessionFactory;
    static {
        try {
            sessionFactory = new Configuration().configure("/hibernate.cfg.xml").buildSessionFactory();
        }
        catch (Throwable ex) {
            System.err.println("Initial SessionFactory creation failed. " + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

Снимок экрана до tx.commit ()

http://img808.imageshack.us/img808/9624/screendebugger2.png

Ответы [ 3 ]

2 голосов
/ 15 декабря 2010

Это означает (как вы предположили), что ваша коллекция пуста.Но это не связано с отложенной загрузкой - отладчик позволит вам загрузить коллекцию.Возможно, он пуст по другой причине.Подтвердите это, показав collection.size().

Другая часть проблемы - каскад.Если вы определили каскад delete-orphan, то либо удалите его, либо убедитесь, что коллекция действительно заполнена.

0 голосов
/ 16 декабря 2010

Если вы обновите объект Project в новой транзакции, вам, вероятно, следует связать объект с новым сеансом, используя

session.merge(project)

Возможно, он обнаружит неинициализированный PersistentSet, заменит его новым из нового сеанса и будет следить за тем, чтобы записи набора не были удалены. В противном случае Hibernate, возможно, не сможет обработать Set, поскольку созданная им транзакция уже закрыта и предполагает, что она пуста.

0 голосов
/ 16 декабря 2010

Вам не нужен звонок «обновить».

Следующий код:

Project proj = this.projService.findProjectById(p.getId());
proj.setName(p.getName());
proj.setDescription(p.getDescription());

В таком случае обновление не требуется, поскольку ссылка на proj постоянна и все изменения в ней будут сохранены. Это особенность гибернации и других ORM, известных как прозрачное постоянство.

см. здесь для получения дополнительной информации о методе обновления гибернат.

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