В Hibernate при использовании CascadeType.ALL сохранение верхнего объекта вызывает ненужные обновления связанных объектов - PullRequest
3 голосов
/ 29 февраля 2012

Имейте класс сущности (Song) с сопоставлением @OneToMany с другой сущностью (CoverArt) и каскадом, установленным на ALL, поскольку казалось, что проще просто сохранить основной объект и позволить ему позаботиться о сохранении обложки

@Audited
@Entity
public class Song
{
    @Id
    @GeneratedValue
    private Integer recNo;

    @Version
    private int version;

    @OneToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    private List<CoverArt> coverArts;

    ....

}

Но позже я обнаружил в коде, что я только что извлек и экземпляр класса из базы данных, а затем в течение сеанса изменил только одно поле в сущности Song, что заставило бы его обновить все сущности обложки, связанные с эта песня, хотя для обложки ничего не изменилось, почему она это делает?

Кроме того, я не думаю, что это вызывает проблему, но я использую Envers, и (казалось бы) ненужные дополнительные обновления таблицы CoverArt приводят к тому, что Envers создает ненужные таблицы аудита.

Если я удаляю аннотацию CascadeType, изменение одного поля не приводит к обновлению объектов обложки, и все работает нормально, пока я добавляю дополнительную логику для добавления обложки, но я надеялся, что не сделал нужно сделать это.

Ответы [ 2 ]

1 голос
/ 14 мая 2015

У меня есть точная проблема с моим собственным приложением.У меня есть 3 один ко многим с cascade = {CascadeType.ALL}

Может кто-нибудь дать мне пример, который работает с правильным повторным использованием сессии.Мой код:

public class HibernateUtil {

private static final SessionFactory sessionFactory = buildSessionFactory();

private static SessionFactory buildSessionFactory() {
    try {
        // Create the SessionFactory from hibernate.cfg.xml
        Configuration conf = new Configuration().configure();
        ServiceRegistry sr = new StandardServiceRegistryBuilder().applySettings(conf.getProperties()).build();
        SessionFactory sf = conf.buildSessionFactory(sr);
        return sf;   
    }
    catch (HibernateException ex) {
        // Make sure you log the exception, as it might be swallowed
        System.err.println("Initial SessionFactory creation failed." + ex);
        throw new ExceptionInInitializerError(ex);
    }
}

public static SessionFactory getSessionFactory() {
    return sessionFactory;
}

}


public groupelti.lims.persistence.vo.LotEchantillonRegulier modifier(groupelti.lims.persistence.vo.LotEchantillonRegulier ler) throws DAOException {

    // validation
    if (ler == null) {
        throw new IllegalArgumentException();
    }
    if (ler.getId() == null) {
        throw new IllegalArgumentException();
    }
    if (ler.getId() <= 0) {
        throw new IllegalArgumentException();
    }

    // traitement
    Session session = HibernateUtil.getSessionFactory().getCurrentSession();
    session.beginTransaction();

    try {
        session.update(ler);
        session.getTransaction().commit();
    } catch (PropertyValueException e) {
        logger.info("" + e.getMessage());

        session.getTransaction().rollback();
        throw new DAOException("Voir log.", e);
    } catch (ConstraintViolationException e) {
        logger.info("" + e.getMessage());

        session.getTransaction().rollback();
        throw new DAOException("Voir log.", e);
    } catch (GenericJDBCException e) {
        logger.info("" + e.getMessage());

        session.getTransaction().rollback();
        throw new DAOException("Voir log.", e);
    } catch (TransientObjectException e) {
        logger.info("" + e.getMessage());

        session.getTransaction().rollback();
        throw new DAOException("Voir log.", e);
    } finally {
        try {
            session.close();
        } catch (SessionException e) {
            //do nothing
        }
    }

    return ler;
}

contact genest@gmail.com С уважением, Матье

1 голос
/ 08 марта 2012

Кажется, я исправил проблему, я использовал анти-шаблон создания нового сеанса, а затем закрывал его всякий раз, когда извлекал что-либо из БД, вместо того, чтобы передавать метод существующему сеансу и закрывать сеанс только после того, как закончил с объектом, исправление этого устранило проблему.

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