Hibernate 挂起或引发延迟初始化,没有会话或会话已关闭

2024-06-20

我正在增强旧的 Spring/Hibernate 应用程序,但我陷入困境。我有一种方法可以读取 3000 多行长的文件,每行都有一条记录,必须与数据库中的某些内容进行比较,然后必须将寄存器添加到数据库(多对多表)。

表和关系是

Branch have 多种产品 , Product are in 许多分行.

Products have 许多产品, and a Category has 许多产品

还有更多的桌子在那里并且工作正常。

The new我创建的表/对象是分支、产品、分支到产品.

产品有一组 BranchToProduct对象,有 3 个字段

我需要将 BranchToProduct 对象添加到 Product 集合中,并根据从文件每一行获取的信息填充 3 个字段。

我添加了一行简单的行,应用程序抛出:

产品= ProductDAO.findByModel(stringModel);

未能延迟初始化 角色集合: com.bamboo.catW3.domain.Product.products, 没有会话或会话已关闭

如果我进入休眠映射(hbm 文件)并设置关系product_to_products 懒惰 = false,该行单独运行良好,但如果我尝试将其放在文件周期中,应用程序始终挂在正在处理的第 18 行,不会无论我使用哪个文件或内容的顺序,控制台都会停止工作,必须关闭 java 杀死进程。

不管怎样,在调试中,我得到了很多 HQL 来进行简单的查找,13 行 HQL 直到我在lazy = true时得到错误,以及当我使用lazy = false并将其放入循环中时得到很多行。

我想我应该尝试用lazy=true来解决这个问题。

这种情况让我不禁思考:

1.- 当lazy=true时。为什么我无法在该方法中运行该命令的一行,但它在该类的其他方法上运行良好?

顺便说一句,这是一个名为 CatalogFacade 的类,它实现了其他类的方法: (CategoryFacade,ContainerFacade,ProductFacade,ProductOptionFacade,ProductStatusFacade,UserFacade,EmailFacade,FileFacade,BranchOfficeFacade)

这是代码
产品Dao.find():

public Product find(Integer id) throws DataAccessException {

        Product product= (Product) super.find(Product.class, id);


        if(product!=null){
            product.setProductAttributes(new TreeSet<ProductAttribute>(product.getProductAttributes()));

            for (Product ptp : product.getProducts()){
               ptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes()));

             }

         } 

异常是在这一行的最后抛出的:

pptp.setProductAttributes(new TreeSet<ProductAttribute>(ptp.getProductAttributes()))  

在 Intelij 的调试器中,我可以看到查询中错误形成的对象:

Product.getProducts() = {org.hibernate.collection.PersistentSet@4312}无法计算表达式方法抛出“org.hibernate.LazyInitializationException”异常。

不过其他属性还是可以的。该产品在数据库中甚至没有其他产品。

UPDATE

深入挖掘内部情况

产品.find(int)

在收到异常之前的行中,我们可以在调试中看到product.products数组有错误,而不是您可以看到的值lazyInitialitationException。How ever,如果我从另一个方法调用它,则找到该数组。所以它不可能在里面虽然该方法仅接收一个整数。

此外,我们发现这种情况在应用程序的整个生命周期中都发生过,有时工作人员复制了类似的方法,但将其更改为将此损坏的数组设置为 null。所以我 100% 确定这个应用程序消耗的资源比它应该消耗的资源多。

它有 Flex 中的视图,以及后来创建的 JSTL 中的视图,并且根据调用方法的人,对于相同的方法以不同的方式抛出异常。

添加更多信息。这就是在抽象 DAOImpl 中实现 Product.find 的方式:

public final Object find(Class clazz, Integer id) throws DataAccessException{

        return getHibernateTemplate().get(clazz,id);
}

这是我的事务管理器配置,fillip 第一个答案中描述的注释方法不起作用:

<bean id="catalogFacade" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager">
        <ref local="transactionManager"/>
    </property>
    <property name="target">
        <ref local="catalogFacadeTarget"/>
    </property>
    <property name="transactionAttributes">
        <props>
            <prop key="add*">PROPAGATION_REQUIRED</prop>
            <prop key="save*">PROPAGATION_REQUIRED</prop>
            <prop key="update*">PROPAGATION_REQUIRED</prop>
            <prop key="delete*">PROPAGATION_REQUIRED</prop>
            <prop key="remove*">PROPAGATION_REQUIRED</prop>
            <prop key="get*">PROPAGATION_SUPPORTS,readOnly</prop>
            <prop key="find*">PROPAGATION_SUPPORTS,readOnly</prop>
            <prop key="contains*">PROPAGATION_SUPPORTS,readOnly</prop>
            <prop key="login*">PROPAGATION_SUPPORTS,readOnly</prop>
        </props>
    </property>
</bean>

您收到延迟初始化异常,因为您的会话在访问 Product 的成员变量之前已关闭。当执行以下行时:

Product product= (Product) super.find(Product.class, id)

Hibernate 打开一个会话,检索您要查找的内容,然后关闭会话。任何具有lazy=true的字段都是not此时已检索;相反,这些字段由代理填充。当您尝试检索代理对象的实际值时,它将尝试使用活动会话返回数据库来检索数据。如果找不到会话,您会看到所看到的异常。设置lazy=true有好处,因为它可以防止立即加载整个对象图;嵌套对象将保持不变,直到您特别要求它们为止。

有两种常见的技术可以解决您的问题。第一个您已经确定,即设置lazy=false。如果产品始终具有产品属性,并且您通常将产品及其属性一起使用,那么这很好。如果您经常只需要 Product 对象而不需要其属性,则会创建不必要的数据库负载。

第二种技术是使用 Spring 注释将方法标记为事务性的。

@Transactional
public Product find(Integer id) throws DataAccessException {

}

一些注意事项:

  1. 你需要一些额外的 交易配置 工作(@Transactional 注释 还不够)。看here http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html为了 更多信息。
  2. 最佳实践要求您在服务层而不是数据访问层中注释方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Hibernate 挂起或引发延迟初始化,没有会话或会话已关闭 的相关文章

随机推荐