In Hibernate when using CascadeType.ALL saving top entity causes uneccssary updates to related entities

StackOverflow https://stackoverflow.com/questions/9490967

Pergunta

Have an entity class (Song) with a @OneToMany mapping to another entity (CoverArt), and cascade set to ALL because it seemed easier to just have to save the main entiy and let it take care of persisting the cover art

@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;

    ....

}

But I found at a later point in the code if I just retrieved and instance of the class from the database and then within session modified just one field in the Song entity that would cause it to update all the cover art entities linked to that song even though nothing had changed for the cover art, why is it doing this ?

Also, I don't think it causes the problem but I am using Envers and the (seemingly) needless extra updates to the CoverArt table have the knock effect of causing Envers to create unneccessary Audit Tables as well.

If I remove the CascadeType annotation modifying the one field does not cause the cover art entities to be updated and everything works okay as long as I add the extra logic for when I do add cover art but I was hoping I didn't need to do this.

Foi útil?

Solução

I seemed to have fixed the problem I was using the anti-pattern of creating a new session and then closing it whenever I retrieved anything from the DB rather than passing the method an existing session and only closing the session once I've finished with the object, fixing this has fixed the problem.

Outras dicas

I have the exact issue with my own application. I have 3 one to many with cascade = {CascadeType.ALL}

Can someone give me an example that work with proper session reuse. My code :

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 Regards, Mathieu

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top