在Hibernate中,当使用CascadeType.ALL保存顶级实体时,会对相关实体进行不必要的更新



拥有一个实体类(Song),该实体类具有到另一个实体(CoverArt)的@OneToMany映射,并级联设置为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注释,修改一个字段不会导致封面艺术实体被更新,只要我添加了添加封面艺术时的额外逻辑,一切都可以,但我希望我不需要这样做。

我似乎已经解决了我使用的反模式的问题,即创建一个新的会话,然后每当我从DB中检索到任何东西时都关闭它,而不是向方法传递一个现有的会话,只有在我完成对象后才关闭会话,解决了这个问题。

我自己的应用程序确实有问题。我有3个一对多级联={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;
}

联系人genest@gmail.com问候,Mathieu

相关内容

  • 没有找到相关文章

最新更新