2010-06-23 104 views
1

我最近采用了我们项目的数据库/休眠方面,并且在理解关于使用管理会话的设计基础知识方面遇到了很多麻烦。我应该使用非静态会话的静态吗?

我们有一个util类,它包含一个只初始化一次的静态会话。会话的检索由系统中的每个DAO通过一个静态方法getBoundSession()来使用。该应用程序全天候运行。这是一个常见的设计?

其中一个非常有用的好处是可以在整个业务逻辑层中使用域对象上的懒惰属性/集合,因为会话始终处于打开状态。另一个好处是,retreived对象将保持在会话中缓存。

我觉得我们必须以一种错误的方式使用Hibernate,看起来只有一次永久打开的会话似乎不正确。当单独的线程正在使用util类时,它也会导致问题,从而共享会话。另一方面,我无法找到一种方法来实现上述优点(特别是第一种)采用不同的设计。任何人都可以对此有所了解吗?

感谢

詹姆斯

回答

2

我们有一个util类,它包含一个只初始化一次的静态会话。会话的检索由系统中的每个DAO通过一个静态方法getBoundSession()来使用。该应用程序全天候运行。这是一个常见的设计?

不是这样。客户端/服务器应用程序中的最常见模式是会话每请求和一个会话每个应用程序多用户应用程序中的方法不仅是反模式,它是完全错误的:

  • A Session不是线程安全的。
  • 如果您希望保持对象状态和数据库同步,您应该在Hibernate异常之后回滚事务并返回关闭Session
  • 如果保持打开时间过长,Session将无限增长。

你真的需要阅读整个Chapter 11. Transactions and Concurrency

另一方面,我无法找到一种方法来实现上述优点(特别是第一种)与不同的设计。

可以使用OSIV(Open Session In View)模式或明确载入每个流需要的内容。如果您想从全局缓存中受益,请使用二级缓存。

+0

非常感谢您的回复。我一定会离开并阅读第11章。如果你不介意的话,最后一个问题是:我们有一个7级的类层次结构(通常是一对多关系),我担心显式加载这个层次结构将是非常重要的昂贵而没有延迟加载。这种紧密耦合的领域模型是否具有设计缺陷?我认为这一定是我们静态会话背后的推理。 – James 2010-06-23 16:22:55

+0

@James:如果你不使用OSIV模式,我不是故意要说“不要使用延迟加载”,而是要明确*提取所需的数据。不,我不认为你的设计是有缺陷的。 – 2010-06-23 16:36:30

+0

假设我们有一个层次:'客户'有许多'订单'有许多'产品'有许多'材料' 由于我们已经使用了一个静态会话,在总线逻辑中一个客户被加载,通过从方法到方法延迟加载成员许多次 - 比如计算每个订单的产品数量,以及订单中最昂贵的材料。 如果会话已关闭,则延迟加载无用,因此业务逻辑无法导航对象图。所以我只能想到业务层管理会话(这看起来很糟糕?),或者删除客户的深度并添加DAO,例如查找最昂贵的材料。 – James 2010-06-23 17:19:50

1

保持会话打开的时间过长是正常(虽然这不应该是永恒:-)会话应该确定工作的单位 - 一套连贯的逻辑上属于一起的查询/更新。您可以在您的应用中识别这些单位 - 例如客户端请求或对话?如果是这样,请为其中的每个创建一个单独的会话。

您还应该明确地为每个线程使用一个单独的会话(通常,一个工作单元由单个线程处理)。一个简单的方法是使用thread local storage

0

这是一种反模式。

如果您为所有请求使用一个会话。然后考虑几乎同时运行的100个客户端(100个请求/线程)。你从会话中分离出一些东西,但是另一个用户重新加载了相同的东西。您将需要同步化,这将达到性能。而且你会完全随机的行为,这将是噩梦调试。

SessionFactory是静态/每应用程序,而不是Session。工厂应该根据需要建立一个会话。在休眠时阅读sessions and transactions文档。

相关问题