为什么不使用Spring的OpenEntityManagerInViewFilter
虽然在Spring的OpenSession / EntityManagerInViewFilter的主题上写了很多post,但是我找不到任何提及它的缺陷。 据我所知,并假设使用@Transactional服务层的典型分层Web应用程序体系结构,filter的工作原理如下:
- filter拦截一个servlet请求
- filter打开一个EntityManager并将其绑定到当前线程
- networking控制器被调用
- Web控制器调用服务
- 事务拦截器开始一个新的事务,检索线程绑定的EntityManager并将其绑定到事务
- 服务被调用,用EntityManager做一些东西,然后返回
- 事务拦截器刷新EntityManager然后提交事务
- networking控制器准备视图,然后返回
- 视图被build立
- filterclosuresEntityManager并从当前线程中解除绑定
在步骤8和9中,由线程的EntityManager加载的对象仍然被pipe理。 因此,如果在这些步骤中使用了惰性关联,那么将使用仍然打开的EntityManager从数据库加载它们。 据我所知,每个这样的访问都要求数据库打开一个事务。 Spring的事务pipe理将不知道这一点,因此我称之为“隐式事务”。
我看到2个问题:
- 加载多个惰性关联会导致多个数据库事务,这可能会影响性能
- 根对象及其惰性关联会加载到不同的数据库事务中,因此数据可能会过时(例如,线程1加载的根,线程2更新的根关联,线程1加载的根关联)
一方面,这两个问题似乎足以拒绝使用这个filter(性能命中,数据不一致)。 另一方面,这个解决scheme非常方便,避免写几行代码,问题1可能不那么明显,问题2可能是纯粹的偏执狂。
你怎么看?
谢谢!
如您所说,OpenSessionInViewfilter在Web应用程序中非常方便。 关于你提到的限制:
1)加载几个惰性关联会导致多个数据库事务,这可能会影响性能。
是的,去DB往往会导致性能问题。 理想情况下,您想要在一次旅行中获取所有需要的数据。 考虑使用Hibernate的join-fetch。 但是从数据库中获取太多的数据也会很慢。 我使用的经验法则是如果每次绘制视图时都需要数据,则使用连接抓取; 如果在大多数情况下不需要数据,我会让Hibernate在需要的时候懒惰地获取它 – threadlocal打开会话然后帮助。
2)根对象和它的惰性关联被加载到不同的数据库事务中,因此数据可能是陈旧的(例如,线程1加载的根,线程2更新的根关联,线程1加载的根关联)。
想象一下在JDBC中编写这个应用程序 – 如果应用程序的一致性要求要求根和叶两者都应该加载在同一个txn中,则使用联接提取。 如果不是的话,通常情况下,延迟提取不会导致任何一致性问题。
恕我直言,与OpenSessionInView更重要的缺点是当你希望你的服务层在非web上下文中重用。 从你的描述来看,你似乎没有这个问题。
我听说过OpenSessionInView和延迟加载的主要参数是事务的过量和对性能的负面影响。 在使用率低的应用程序上使用非常方便,但在高规模应用程序中,我build议使用旧式的完全填充的DTO(数据传输对象)。
我在OpenSessionInViewFilter遇到的一个主要问题是使用AJAX应用程序和JavaScript。 如果您使用JavaScript来呈现网格或某些UI组件; 有一个懒加载(考虑你打开filter); 并抛出exception。 你的应用程序UI渲染是一个折腾。 数据可能永远不会显示,页面开始抛出奇怪的JavaScriptexception,您需要编写额外的js代码来处理。 而你正在向用户公开数据库exception(不是一个好主意)。
在常规应用程序中,可以捕获这些exception,并引发有效的用户exception。
如果您的应用程序是多层体系结构(在不同的JVM上部署了视图层,服务层部署在不同的VM上),那么保持会话处于打开状态是没有意义的。 如果你的服务层独立于你的应用层,我会看到不使用任何OpenSessionViewFilter。
- hibernate问题 – “使用@OneToMany或@ManyToMany定位未映射的类”
- Hibernate的两个configuration文件的目的是什么?
- 什么是好的博客阅读有关java,spring,hibernate,maven?
- hibernate – 批量更新返回来自更新的意外行数:0实际行数:0预期:1
- 错误:没有validation器可以findtypes:java.lang.Integer?
- buildSessionFactory()在hibernate 4中被弃用了吗?
- 使用复合主键和注解映射ManyToMany:
- 冬眠-公地注解-4.0.1.Final.jar; 无效的LOC头(坏签名)?
- 注释@Transactional。 如何回滚?