Spring Open Session in View

Source: Internet
Author: User

proposed: The session is closed at the application layer, so persistence is applied at the application level, but the session is closed when the view layer is persisted Resolution: Session deferred to view layer and then closed principle: Session (entire Requestscope) Flushmode-->flushmode.never, (read only automatic-->flushmode.auto, premise: Have transaction )。 Manual Solution:
    1. Session. Setflushmode(flushmode. AUTO);
    2. Session. Save(user);
    3. Session. flush();

If the session is closed in the service (or Dao) layer without using the open session in view provided by spring, the lazy loading is true if the relationship set is initialized within the application layer, as    Company.getemployees (), otherwise hibernate throw session already closed Exception; Open Session in view provides a convenient way to solve the problem of lazy loading.

It has two configurations, Opensessioninviewinterceptor and Opensessioninviewfilter (see Springside), with the same functionality, Just one in the Web. XML configuration, the other in Application.xml configuration only.

Open session in view keeps hibernate session open during request binding session to the current thread, so that the session can be used throughout the request. As in the view Layer PO can also be lazy loading data, such as ${company.employees}. When the view layer logic is complete, the session is automatically closed via the filter's Dofilter method or Interceptor's Posthandle method.


Opensessioninviewinterceptor Configuration
  1. <beans>
  2. <bean name="Opensessioninviewinterceptor"
  3. class="Org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" >
  4. <property name="Sessionfactory" >
  5. <ref bean="Sessionfactory"/>
  6. </property>
  7. </bean>
  8. <bean id="urlmapping"
  9. class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
  10. <property name="interceptors" >
  11. <list>
  12. <ref bean="Opensessioninviewinterceptor"/>
  13. </list>
  14. </property>
  15. <property name="Mappings" >
  16. ...
  17. </property>
  18. </bean>
  19. ...
  20. </beans>
Opensessioninviewfilter Configuration
  1. <web-app>
  2. ...
  3. <filter>
  4. <filter-name>hibernateFilter</filter-name>
  5. <filter-class>
  6. Org.springframework. Orm. Hibernate3. Support . opensessioninviewfilter
  7. </filter-class>
  8. <!--singlesession default is True, if set to false it is useless opensessioninview --
  9. <init-param>
  10. <param-name>singleSession</param-name>
  11. <param-value>true</param-value>
  12. </init-param>
  13. </filter>
  14. ...
  15. <filter-mapping>
  16. <filter-name>hibernateFilter</filter-name>
  17. <url-pattern>*. do</url-pattern>
  18. </filter-mapping>
  19. ...
  20. </web-app>

A lot of people mention an error in using the Opensessioninview process:

    1. Org.springframework. Dao. invaliddataaccessapiusageexception:write Operations
    2. is not allowed in read-only mode (Flushmode. Never)-Turn your Session into
    3. Flushmode. AUTO or remove ' readOnly ' marker from transaction definition

Look at some of the ways in Opensessioninviewfilter.

  1. protectedvoid dofilterinternal(HttpServletRequest request, HttpServletResponse Response,filterchain Filterchain)throwsServletexception,IOException{Sessionfactory sessionfactory = lookupsessionfactory(); Logger.Debug("Opening Hibernate Session in Opensessioninviewfilter"); Session session = GetSession(sessionfactory); Transactionsynchronizationmanager.Bindresource (  Sessionfactory,  new  sessionholder try  {  filterchain.  Dofilter}  finally  {  Transactionsynchronizationmanager.  unbindresource (Sessionfactorydebug ( "Closing Hibernate Session in Opensessioninviewfilter"  } }&NBSP;
  2. protected  session getsession ( Sessionfactory sessionfactory)   throws Dataaccessresourcefailureexception {  Session session = Sessionfactoryutils.getsession (Sessionfactory,  true  setflushmode (Flushmode.  Never return  session; }
  3. protected void CloseSession(Session session, Sessionfactory Sessionfactory) throws Cleanupfailuredataaccessexception {sessionfactoryutils.  Closesessionifnecessary(Session, Sessionfactory); }

Can see Opensessioninviewfilter in GetSession, will get back to the session of the flush mode set to Flushmode.never. The sessionfactory is then bound to the Transactionsynchronizationmanager so that the entire request process uses the same session, after which the binding of the sessionfactory is removed, Finally Closesessionifnecessary determines whether the session is closed based on whether the session has been bound to the transaction. In this process, if hibernatetemplate found from the current session is not READONLY transaction, will get to the Flushmode.auto Session, so that the method has write permissions.

  1. Public static void Closesessionifnecessary(Session session, Sessionfactory Sessionfactory)
  2. throws Cleanupfailuredataaccessexception {
  3. If (session = = null | | Transactionsynchronizationmanager. hasresource(sessionfactory)) {
  4. return;
  5. }
  6. Logger. Debug("Closing Hibernate Session");
  7. Try {
  8. Session. Close();
  9. }
  10. Catch (Jdbcexception ex) {
  11. SQLException underneath
  12. Throw New cleanupfailuredataaccessexception("Could not close Hibernate session", ex. ) Getsqlexception());
  13. }
  14. Catch (Hibernateexception ex) {
  15. Throw New cleanupfailuredataaccessexception("Could not close Hibernate session", ex);
  16. }
  17. }

That is, if there is not ReadOnly transaction can be converted from flush.never to Flush.auto, with insert,update,delete operation Rights, if there is no transaction, And without the flush model being artificially set, the whole process of dofilter is flush.never. So the method protected by transaction has write permission, not protected.

Use spring's transaction declaration to make the method subject to transaction control
  1.   <bean id= "basetransaction" class= " Org.springframework.transaction.interceptor.TransactionProxyFactoryBean "          Abstract = "true" >         <property name= "TransactionManager" ref= "TransactionManager"/>   & nbsp     <property name= "Proxytargetclass" value= "true"/>         <property name= " Transactionattributes >             <props>           &NBS P     <prop key= "get*" >PROPAGATION_REQUIRED,readOnly</prop>                 <prop key= "find*" >PROPAGATION_REQUIRED,readOnly</prop>         & nbsp       <prop key= "load*" >PROPAGATION_REQUIRED,readOnly</prop>         & nbsp       <prop key= "save*" >PROPAGATION_REQUIRED</prop>           &nbsp     <prop key= "add*" >PROPAGATION_REQUIRED</prop>               & nbsp <prop key= "update*" >PROPAGATION_REQUIRED</prop>                 < Prop key= "remove*" >PROPAGATION_REQUIRED</prop>             </props>         </property>     </bean>
  2. <bean id= "UserService" parent= "basetransaction" > <property name= "target" > <bean class= " Com.phopesoft.security.service.impl.UserServiceImpl "/> </property> </bean>

For the above example, the method beginning with Save,add,update,remove has a writable transaction, if there is a method, such as named Importexcel (), because there is no transaction and no write permission, then if there is insert inside the method, Update,delete operation, you will need to manually set the flush model to Flush.auto, as

    1. Session. Setflushmode(flushmode. AUTO);
    2. Session. Save(user);
    3. Session. flush();

Although the open Session in view looks good, there are many side effects. Looking back at the Opensessioninviewfilter Dofilterinternal method code above, this method is actually called by the Dofilter of the parent class, so We can learn about the Opensessioninviewfilter invocation process: request (requests)->open session and start Transaction->controller->view (JSP)- > End transaction and close session.

Everything seems to be right, especially if there is no problem at the time of the local development test, but imagine if a step in the process is blocked, then the connection is occupied and not released. The most likely to be blocked is to write JSP this step, on the one hand may be the page content is large, Response.Write time is long, on the other hand may be slow, the server and the user between the transmission time long. When a large number of such cases occur, there is insufficient connection pool connection, causing the page suspended animation phenomenon.

Open Session In view is a double-edged sword, on the public web content of large-volume website please use with caution

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.