Why is hibernate open session in view considered a bad practice?

Why is hibernate open session in view considered a bad practice?

为什么hibernate open session in view不推荐用?

opensessioninview

OpenSessionInView是一种模式,不管是自己用Filter实现的,还是用Spring官方的,都是一种不被推荐的模式,称为反模式“Anti-Pattern”。

OpenSessionInView这一模式为解决Hibernate延迟加载问题,一般情况下如果在事务之外,Service之外,Jsp中,调用延迟加载的属性,会出现 proxy no session之类的错误,因为这时session关闭了,当前的实体已经是游离态的。未解决这个问题,出现了一种OpenSessionInView模式,这个模式可以自己实现,Jboss,也可以用Spring官方的OpenSessionInViewFilter OpenEntityManagerInViewFilter

这种模式大概是,每一个请求开一个Session或者可以开多个延时关闭的Session,有的整个请求只开一个事务就太不方便了,一般可以多事务,多提交,只是Session不关闭,多Session的情况会损失一级缓存的,单一session也有问题,没看懂。总之就是不让session关闭的方式来,在任何地方“自由的”访问Entity,可以说使用起来非常方便。

可能产生的问题,[Jboss]中提到,如果是Jsp中访问,输出页面数据的缓冲区是8k,8k8k...来输出页面,如果DAO层发生异常,异常信息会被直接输出。还提到一些框架是如何避免的,不用默认缓冲区,用自建的。 还有可能,页面端输出的延迟加载的数据已经和父级数据不一致了,父级数据还是之前的,页面延迟输出的时候,可能父子数据都变了,但延迟加载的数据跟父数据不一致。还有就是N+1的问题,数据少,页面只需要一两个实体,没有关系,如果页面是个有大量数据的表格,这时候性能就会受影响了。因为在select child的时候采用的是(select * from child where parentid="1")x N 次,而不是select * from child where parentid in [1,2,3...]。

最重要的是,OpenSessionInView模式破坏了项目结构,DAO层只给Service层开放访问,除此之外不应该给任何层访问,如果页面访问Entity延迟加载属性,相当于直接访问了DAO层。

老外也说,没什么好的解决办法,短期可能用一下,长期还是自己写查询。尽量不用延时加载,不是说访问一下加载天一样的大数据,控制好。Service和DAO多写几个方法,eager加载的地方就用 join-fetch,还是填充DTO,多调用service几次。


References

he-opensessioninview-antipattern

csdn

open-session-in-view-pattern-spring-jpa

open-session-in-view-pattern-pros-and-cons

the-open-session-in-view-anti-pattern

what-is-select-n1

n-plus-one

spring-3-part-8-spring-hibernate-open

hibernate-open-session-in-view-transaction-per-request

why-not-to-use-springs-openentitymanagerinviewfilter

spring-3-2-hibernate-4-opensessioninviewfilter

configuring-opensessioninviewfilter-with-spring-3-and-servlet-3

Related Article