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
Hibernate 为什么不使用Spring';s OpenEntityManager视图过滤器_Hibernate_Spring_Lazy Loading - Fatal编程技术网

Hibernate 为什么不使用Spring';s OpenEntityManager视图过滤器

Hibernate 为什么不使用Spring';s OpenEntityManager视图过滤器,hibernate,spring,lazy-loading,Hibernate,Spring,Lazy Loading,虽然很多帖子都是关于Spring的OpenSession/EntityManagerInViewFilter的,但我找不到任何提到它的缺陷的帖子。据我所知,并假设使用@Transactional服务层的典型分层web应用程序体系结构,过滤器的工作原理如下: 过滤器拦截servlet请求 过滤器打开EntityManager并将其绑定到当前线程 Web控制器被称为 Web控制器调用服务 事务拦截器开始一个新事务,检索线程绑定的EntityManager并将其绑定到事务 调用服务,使用EntityM

虽然很多帖子都是关于Spring的OpenSession/EntityManagerInViewFilter的,但我找不到任何提到它的缺陷的帖子。据我所知,并假设使用@Transactional服务层的典型分层web应用程序体系结构,过滤器的工作原理如下:

  • 过滤器拦截servlet请求
  • 过滤器打开EntityManager并将其绑定到当前线程
  • Web控制器被称为
  • Web控制器调用服务
  • 事务拦截器开始一个新事务,检索线程绑定的EntityManager并将其绑定到事务
  • 调用服务,使用EntityManager执行一些操作,然后返回
  • 事务拦截器刷新EntityManager,然后提交事务
  • Web控制器准备视图,然后返回
  • 视图已建立
  • 筛选器关闭EntityManager并将其从当前线程中解除绑定
  • 在步骤8和9中,由线程的EntityManager加载的对象仍然处于管理状态。因此,如果在这些步骤中接触到惰性关联,则将使用仍然打开的EntityManager从数据库中加载它们。据我所知,每次访问都需要数据库打开一个事务。Spring的事务管理将不知道这一点,因此我称之为“隐式事务”

    我发现这有两个问题:

  • 加载多个惰性关联将导致多个数据库事务,这可能会影响性能
  • 根对象及其惰性关联加载在不同的数据库事务中,因此数据可能已过时(例如,由线程1加载的根、由线程2更新的根关联、由线程1加载的根关联)
  • 一方面,这两个问题似乎足以拒绝使用此过滤器(性能影响、数据不一致)。另一方面,这个解决方案非常方便,避免了编写几行代码,问题1可能不那么明显,问题2可能纯粹是偏执狂

    你觉得怎么样


    谢谢

    正如您所说,OpenSessionInView过滤器在web应用程序中非常方便。关于你提到的限制:

    1) 加载多个惰性关联将导致多个数据库事务,这可能会影响性能

    是的,经常访问数据库可能会导致性能问题。理想情况下,您希望在一次旅行中获取所需的所有数据。考虑为此使用Hibernate连接获取。但是从数据库获取太多数据也会很慢。我使用的经验法则是,如果每次绘制视图时都需要数据,则使用连接获取;如果在大多数情况下不需要数据,我会让Hibernate lazy在需要时获取数据——threadlocal open会话会有帮助

    2) 根对象及其惰性关联加载在不同的数据库事务中,因此数据可能已过时(例如,由线程1加载的根、由线程2更新的根关联、由线程1加载的根关联)

    想象一下用JDBC编写这个应用程序——如果应用程序的一致性要求根和叶都应该加载到同一个txn中,那么就使用连接抓取。如果不是,通常情况下,延迟抓取不会导致任何一致性问题


    我想,OpenSessionInView更重要的缺点是当您希望在非web上下文中重用服务层时。根据您的描述,您似乎没有这个问题。

    我听到的反对OpenSessionInView和延迟加载的主要论点是事务过多,对性能有负面影响。在低使用要求的应用程序上使用非常方便,但在高规模应用程序上,我建议使用老式的完全填充DTO(数据传输对象)。

    我在OpenSessionInViewFilter中遇到的主要问题之一是使用AJAX应用程序和javascript。如果您使用javascript呈现网格或某些UI组件;有一个延迟负载(考虑到你打开了过滤器);然后抛出一个异常。您的应用程序UI呈现将面临挑战。数据可能永远不会显示,页面开始抛出奇怪的javascript异常,您需要编写额外的js代码来处理这些异常。而且您正在向用户公开数据库异常(这不是一个好主意)


    在常规应用程序中,可以捕获这些异常并抛出有效的用户异常

    如果您的应用程序是一个多层体系结构(部署在不同JVM上的视图层和部署在不同VM上的服务层),那么将会话保持在打开状态是没有意义的。如果您的服务层独立于您的应用程序层,我将看到不使用任何OpenSessionViewFilter