使用休眠回调的优势?

2022-09-02 21:04:53

我无法理解使用Hibernate回调方法的优点,我们是否应该使用它的任何优点或特定用例。

public List findRecentRequests(final int offset, final int length)
{
    List list = getHibernateTemplate().executeFind(new HibernateCallback()
    {
        public Object doInHibernate(Session session) throws HibernateException
        {
            Query q = session.createQuery(FIND_RECENT_REQUESTS);
            q.setFirstResult(offset);
            q.setMaxResults(length);
            return q.list();
        }
    });
    return list;
}

另外一个更重要的问题是,在查询返回值后,HibernateCallback方法是否每次都关闭会话?我有一个用例,每次刷新状态页面时多次调用此函数,因此每次打开会话和查询数据库时都会调用此函数,或者它将查询结果存储在内存中,然后每次我调用此函数时,结果都会从内存中弹出。

我已阅读(参考资料):

默认情况下,spring HibernateTemplate.execute() 会在完成后关闭所有打开的会话。当与惰性初始化一起使用时,您可能会得到一个懒惰初始化异常,如下所示

org.hibernate.LazyInitializationException: 無法初始化 proxy - no Session

如能提及相关文件部分,将不胜感激。

更新:

在我的情况下,我使用ejb事务并将其设置为“支持”,我相信在这种情况下,因为事务设置为支持,它是可选的,因此每次创建新会话和休眠都会查询数据库以获取结果,因此这是我遇到的瓶颈,这是正确的假设吗?


答案 1

关于您为什么使用.简短的答案 - 它允许您访问当前事务绑定的会话,以便执行更复杂的休眠功能。大多数情况下,简单的方法就足够了,但有时您需要转到 .HibernateCallbackHibernateTemplateSession

这个谜题有两个部分。

第一个是通过使用 / OR 注释定义的事务范围。请参阅春季文档/谷歌以获取更多信息。PlatformTransactionManagerTransactionTemplate@Transactional

第二,当你在一个交易中时,会使用一些魔术与当前交易进行交互。HibernateTemplate

所以一个简单的操作就会参与交易。像您的示例这样更复杂的示例也将参与事务。事实上,hTemplate上几乎任何方法都会参与其中。hibernateTemplate.save()

因此,请了解您的问题,即会话何时结束

  • 如果显式使用事务,请参阅上面的第一点,则当事务范围关闭时,将提交事务并关闭会话。
  • 没有事务,Spring 会在每次调用方法时为您创建一个会话,并在之后立即关闭它。这不是首选方法,因为除非您正在做非常简单的事情,否则结果将从会话中分离出来,并且您将获得LazyInit异常。HibernateTemplate

在上面的第二种情况下,需要注意的重要一点是没有显式事务。您受制于连接的自动提交模式,因此您可以在回调中保存,保存,保存,抛出异常。第一次保存可能已经提交,没有交易就没有保证。

我的建议是,在进行任何更新时,请使用事务。

如果所有交易内容对您来说都是新的,请查看交易章节的春季文档。


答案 2

如果你正在使用Spring,你应该在你的存储库或服务层周围使用声明式事务管理来透明地处理这个问题。PlatformTransactionManager 实现将执行适用于给定持久性提供程序的操作。

在数据访问代码不足后,依赖初始化惰性集合被认为是不好的做法 - 这通常意味着你在应用的控制器/视图层中有一些业务逻辑,应该将它们移动到服务层中。


推荐