Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么视图中的Hibernate开放会话被认为是一种不好的做法?_Java_Hibernate_Jpa_Lazy Loading_Open Session In View - Fatal编程技术网

Java 为什么视图中的Hibernate开放会话被认为是一种不好的做法?

Java 为什么视图中的Hibernate开放会话被认为是一种不好的做法?,java,hibernate,jpa,lazy-loading,open-session-in-view,Java,Hibernate,Jpa,Lazy Loading,Open Session In View,您使用什么样的替代策略来避免懒散负载异常 我确实了解,鉴于公开会议存在以下问题: 在不同jvm中运行的分层应用程序 事务只在最后提交,您很可能希望在提交之前得到结果 但是,如果您知道您的应用程序运行在单个vm上,为什么不使用视图中的开放会话策略来缓解您的痛苦呢?因为发送可能未初始化的代理,特别是集合,从性能和理解的角度来看,在视图层中触发hibernate加载可能会带来麻烦 理解: 使用OSIV会“污染”视图层,并与数据访问层相关 视图层没有准备好处理延迟加载时可能发生的HibernateE

您使用什么样的替代策略来避免懒散负载异常

我确实了解,鉴于公开会议存在以下问题:

  • 在不同jvm中运行的分层应用程序
  • 事务只在最后提交,您很可能希望在提交之前得到结果

但是,如果您知道您的应用程序运行在单个vm上,为什么不使用视图中的开放会话策略来缓解您的痛苦呢?

因为发送可能未初始化的代理,特别是集合,从性能和理解的角度来看,在视图层中触发hibernate加载可能会带来麻烦

理解:

使用OSIV会“污染”视图层,并与数据访问层相关

视图层没有准备好处理延迟加载时可能发生的
HibernateException
,但数据访问层可能是

性能:

OSIV倾向于在地毯下拖拽适当的实体加载-您不会注意到您的集合或实体是惰性初始化的(可能是N+1)。更方便,更少控制


更新:有关此主题的更多讨论,请参阅。作者列举了三个要点:

  • 每个延迟初始化将得到一个查询,这意味着每个实体将需要N+1个查询,其中N是延迟关联的数量。如果您的屏幕显示表格数据,那么读取Hibernate的日志就是一个很大的提示,表明您没有按照应该做的去做
  • 这完全破坏了分层架构,因为在表示层中使用DB会弄脏指甲。这是一个概念上的骗局,所以我可以接受,但有一个推论
  • 最后但并非最不重要的一点是,如果在获取会话时发生异常,它将在写入页面期间发生:您无法向用户呈现干净的错误页面,您唯一能做的就是在正文中写入错误消息

  • 如果您使用的是控制反转(IoC)容器,如Spring,您可能需要仔细阅读。本质上,我告诉Spring给我一个Hibernate
    会话
    对象,它的生命周期跨越整个请求(即,它在HTTP请求的开始和结束时被创建和销毁)。我不必担心
    LazyLoadException
    s或关闭会话,因为IoC容器为我管理会话

    如前所述,您必须考虑N+1选择性能问题。您始终可以在以后配置Hibernate实体,以便在性能有问题的地方执行即时加入加载


    bean作用域解决方案不是特定于Spring的。我知道PicoContainer提供了相同的功能,我相信其他成熟的IoC容器也提供了类似的功能。

    我不会说在视图中打开会话被认为是一种不好的做法;是什么给你这样的印象

    在视图中打开会话是使用Hibernate处理会话的一种简单方法。因为它很简单,所以有时过于简单。如果您需要对事务进行细粒度控制,例如在一个请求中有多个事务,那么视图中的开放会话并不总是一个好方法


    正如其他人所指出的,OSIV有一些折衷办法——您更容易出现N+1问题,因为您不太可能意识到您正在启动哪些事务。同时,这意味着您无需更改服务层以适应视图中的微小更改。

    I am v。冬眠时生锈了。。但是我认为在一个Hibernate会话中有多个事务是可能的。因此,事务边界不必与会话开始/停止事件相同

    OSIV,imo,主要是有用的,因为我们可以避免每次请求需要进行DB访问时编写启动“持久性上下文”(也称为会话)的代码


    在您的服务层中,您可能需要调用具有不同事务需求的方法,例如“Required、New Required等”。这些方法唯一需要的是有人(即OSIV筛选器)启动了持久性上下文,因此他们唯一需要担心的是-“嘿,给我这个线程的hibernate会话。。我需要做一些数据库方面的工作。

    我刚刚在我的博客中发布了一些关于何时在视图中使用open session的指导原则。如果您感兴趣,请查看

    • 事务可以在服务层提交-事务与OSIV无关。保持打开状态的是
      会话,而不是正在运行的事务

    • 如果您的应用程序层分布在多台机器上,那么您几乎不能使用OSIV—您必须在通过线路发送对象之前初始化所有需要的内容

    • OSIV是一种很好的、透明的(也就是说,您的代码都不知道它发生了)利用延迟加载的性能优势的方法


      • 以我自己的经验,OSIV并没有那么糟糕。 我所做的唯一安排是使用两种不同的交易: -第一个,在“服务层”中打开,在这里我有“业务逻辑”
        -第二个在视图渲染之前打开这不会有太大帮助,但您可以在此处查看我的主题: *


        我有一些OutOfMemory问题,因为OpenSessionInView和加载了很多实体,因为它们停留在Hibernate缓存级别1中,并且没有垃圾收集(我加载了很多实体,每页有500个项目,但所有实体都停留在缓存中)

        视图中的Open Session采用了错误的方法获取数据。它不让业务层决定如何最好地获取视图层所需的所有关联,而是强制持久性上下文保持打开状态,以便视图层可以触发代理初始化

        • OpenSessionInViewFilter
          调用
          openSessionspring.jpa.open-in-view=false