【问题标题】:Adding @Transactional causes "collection with cascade="all-delete-orphan" was no longer referenced"添加@Transactional 导致“不再引用具有 cascade="all-delete-orphan" 的集合”
【发布时间】:2013-06-11 16:55:17
【问题描述】:

我正在将一个工作项目从 Spring2+Hibernate3 升级到 Spring3+Hibernate4。由于 HibernateTemplate 和 HibernateDAOSupport 已经退役,我做了以下

之前(简化)

public List<Object> loadTable(final Class<?> cls)
{
    Session s = getSession(); // was calling the old Spring getSession
    Criteria c = s.createCriteria(cls);
    List<Object> objects = c.list();
    if (objects == null)
    {
        objects = new ArrayList<Object>();
    }
    closeSession(s);
    return objects;
}

现在(简化)

@Transactional(propagation=Propagation.REQUIRED)
public List<Object> loadTable(final Class<?> cls)
{
    Session s = sessionFactory.getCurrentSession();
    Criteria c = s.createCriteria(cls);
    List<Object> objects = c.list();
    if (objects == null)
    {
        objects = new ArrayList<Object>();
    }
    return objects;
}

我还在 Spring XML 中添加了事务注释声明,并从 Hibernate 属性中删除了它

 "hibernate.current_session_context_class", "org.hibernate.context.ThreadLocalSessionContext"

@Transactional 注释似乎起作用了,正如我在堆栈跟踪中看到的那样

at com.database.spring.DatabaseDAOImpl$$EnhancerByCGLIB$$7d20ef95.loadTable(<generated>)

在初始化期间,上述更改似乎适用于对 loadTable 函数的几次调用,但是当它开始加载具有父级的实体时,我得到“具有 cascade="all-delete-orphan" 的集合不再引用”错误。由于我没有触及任何其他设置/获取父母或孩子的代码,只是试图修复 DAO 方法,而查询只是执行 sql SELECT,任何人都可以看到代码被破坏的原因吗?

问题似乎类似于Spring transaction management breaks hibernate cascade

【问题讨论】:

    标签: spring hibernate


    【解决方案1】:

    这不太可能是 Spring 的问题,而是您的实体处理/定义的问题。当您在关系上使用deleteOrphans 时,底层PersistentSet 不得从实体本身中删除。您只能修改集合实例本身。所以如果你想在你的实体设置器中做一些聪明的事情,那就是原因。

    据我所知,当您在关系的双方都有deleteOrphans 和/或在一个会话中加载/操作双方时,会出现一些问题。


    顺便说一句。我不认为"hibernate.current_session_context_class", "org.hibernate.context.ThreadLocalSessionContext" 是必要的。在我们的项目中,这是我们唯一的配置:

    @Bean
    public LocalSessionFactoryBuilder sessionFactoryBuilder() {
        return ((LocalSessionFactoryBuilder) new LocalSessionFactoryBuilder(
                dataSourceConfig.dataSource()).scanPackages(ENTITY_PACKAGES).
                setProperty("hibernate.id.new_generator_mappings", "true").
                setProperty("hibernate.dialect", dataSourceConfig.dialect()).
                setProperty("javax.persistence.validation.mode", "none"));
    }
    
    @Bean
    public SessionFactory sessionFactory() {
        return sessionFactoryBuilder().buildSessionFactory();
    }
    

    【讨论】:

    • 谢谢帕维尔。我一直在阅读大量博客文章,其中设置父实体被确定为导致此错误的原因。项目中确实有很多“时髦”的实体生成,但我不想在不知道为什么这不是 HibernateTemplate 的问题的情况下触摸它。但我会再看一遍并报告。顺便说一句,我确实从休眠道具中删除了“ThreadLocalSessionContext”。
    【解决方案2】:

    问题在于会话管理。正在执行自己的会话处理的其他模块正在调用相同的事务代码块。雪上加霜的是,一些调用模块是 Spring bean,而另一些是直接用 Hibernate API 风格编写的。这种混乱足以使我们无法立即升级到 Hibernate 4。

    本课的寓意(您喜欢这种英语吗?):在整个项目中使用一致的 DAO 实现,并坚持明确定义的会话和事务管理策略。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-03-14
      • 2011-08-01
      • 2021-01-09
      • 1970-01-01
      • 1970-01-01
      • 2018-03-06
      相关资源
      最近更新 更多