我刚开始使用HQLnate和HSQLDB。在教程中,他们告诉我不要使用反模式“每次操作会话”。但是,每次提交事务时,会话也会关闭。如果getCurrentSession()
关闭会话,我该如何避免使用commit()
?
我对人们通常如何处理会话的范围感到好奇。我在构建Web应用程序时看到了几个示例,其中每个请求有一个会话。在我的情况下,我正在建立一个服务,并不能应用相同的想法。该服务每周7天,每天24小时运行,偶尔会执行一些数据库操作。我应该始终保持数据库会话是活动的,只使用事务作为操作之间的边界(考虑我的事务提交不关闭会话的情况)或者我应该为每个操作创建一个新的(这是反...模式,但怎么回事?)。
提前致谢!
答案 0 :(得分:3)
该行为取决于所使用的CurrentSessionContext的实施情况。默认恰好是ThreadLocalSessionContext,它提供了close-on-commit,但你并不局限于此。
您可以在生命周期的适当开始和结束时使用ManagedSessionContext和绑定/解除绑定会话来配置/构建您喜欢的任何类型的会话范围。您似乎有意义的是,您将条目中的会话绑定到服务的工作单元,并在出口处解除绑定。 (为此建立健壮的代码当然不是一项微不足道的任务。特别要记住,如果一个异常来自其中一个方法,你应该创建一个新的Session
。)
回复评论的评论太大了。
这是默认行为,因为如果没有用户提供额外的工作或配置,它是唯一“安全”的东西。 “提交”是Hibernate能够“看到”的唯一生命周期点,如果你没有帮助它,那么它必须在那里关闭或者让会话永远悬空。
确定潜在的会话生命周期边界需要对您实际执行的操作有相当多的了解。 “这是一项后台服务”并不多。假设它做的事情就像坐着怠速并每隔X分钟醒来一样,做一些工作,然后又回去睡觉另外X分钟,那么这将是一个很好的界限,打开然后关闭一个会话。
当谈论“每次操作的会话”是反模式时,您可能正在使用过度广泛的“操作”定义。
他们的意思是不要做(像你的服务的虚构要求):
在一个会话中执行此操作然后在结束时关闭它是完全合理的。在单线程环境中,您自己在已知边界内管理所有内容,您可以自己打开和关闭会话,而无需使用currentSession
。您只需要确保在发生异常时关闭它。如果您正在侦听操作系统事件,则事件处理将是会话的完美范围。