Session is closed; Nested exception is org.hibernate.SessionException:Session is closed solution

Source: Internet
Author: User
Tags sessions
1. Get the session through the getSession() method for operation
Java code public class Test extends HibernateDaoSupport{ public void save(User user){ this.getSession().save(user);}}
public class Test extends HibernateDaoSupport{
     public void save(User user){
        this.getSession().save(user);
     }
}

The session obtained in this way will not automatically close the connection after the method execution ends, that is to say, we must manually close it through session.close() or releaseSession(session), otherwise it will cause memory leaks or connection exhaustion. . Close manually:
Java code public class Test extends HibernateDaoSupport{ public void save(User user){ Session session = this.getSession(); session.save(user); session.close(); // releaseSession(session); //This method , I have used it, can definitely solve the error of session.close(). }}
public class Test extends HibernateDaoSupport{
     public void save(User user){
        Session session = this.getSession();
        session.save(user);
        session.close();
        // releaseSession(session);
     }
}

If the transaction control is performed on the above method, the spring framework will automatically close the session for us. In this case (session.close()) and then execute the above code, the following exception will be thrown: Java code org.springframework.orm.hibernate3. HibernateSystemException: Session is closed; nested exception is org.hibernate.SessionException: Session is closed… org.hibernate.SessionException: Session is closed
 org.springframework.orm.hibernate3.HibernateSystemException: Session is closed; nested exception is org.hibernate.SessionException: Session is closed

org.hibernate.SessionException: Session is closed

Prompt that the session has been closed. But if you close the session in the code through the releaseSession(session) method, no exception will be thrown. The code of the releaseSession(session) method is as follows:
Java code protected final void releaseSession(Session session) {SessionFactoryUtils.releaseSession(session, getSessionFactory());}
protected final void releaseSession(Session session) {
SessionFactoryUtils.releaseSession(session, getSessionFactory());
}

In other words, it is implemented through the releaseSession method of SessionFactoryUtils:
Java code public static void releaseSession( Session session,SessionFactory sessionFactory) {if (session == null) {return;} // Only close non-transactional Sessions. if (!isSessionTransactional(session,sessionFactory)) {closeSessionOrRegisterDeferredClose (session, sessionFactory );}}
public static void releaseSession(
     Session session,SessionFactory sessionFactory) {
if (session == null) {
return;
}
// Only close non-transactional Sessions.
if (!isSessionTransactional(session,sessionFactory)) {
closeSessionOrRegisterDeferredClose (session, sessionFactory);
}
}

It can be seen that it will judge first.

View the source code of the getSession() method:
Java code protected final Session getSession() throws DataAccessResourceFailureException, IllegalStateException {return getSession(this.hibernateTemplate.isAllowCreate());}
protected final Session getSession()
throws DataAccessResourceFailureException, IllegalStateException {

return getSession(this.hibernateTemplate.isAllowCreate());
}

The getSession() method is implemented internally through one of its overloaded methods getSession(boolean allowCreate). The variable allowCreate is a variable in HibernateTemplate. The default value is true, which means to create a new session. If we call getSession(false) to get the session, then it must be transaction controlled, the reason is: (spring document) Java code protected final org.hibernate.Session getSession() throws DataAccessResourceFailureException, IllegalStateException Get a Hibernate Session, either from the current transaction or a new one. The latter is only allowed if the "allowCreate" setting of this bean's HibernateTemplate is true.
protected final org.hibernate.Session getSession()
throws DataAccessResourceFailureException, IllegalStateException

Get a Hibernate Session, either from the current transaction or a new one. The latter is only allowed if the "allowCreate" setting of this bean's HibernateTemplate is true.

In other words, the getSession() method obtains the session from the current transaction or a new transaction. If you want to obtain the session from a new transaction (that is, when there is no transaction control), you must use allowCreate in HibernateTemplate The value of the variable is "true", and now setting the value of the allowCreate variable to "false" means that the session cannot be obtained from the new transaction, that is, it can only be obtained from the current transaction, so the current method must be controlled by the transaction, otherwise The following exception will be thrown:
Java code java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here...
java.lang.IllegalStateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here ...

At the same time, if transaction control is performed on the method where getSession() is located, then the code similar to the following:
Java code Session session = null; for(int m=0;m<5;m++){ Admin admin = new Admin(); admin.setName("test"); admin.setPassword("098"); session = this .getSession(); session.save(admin);}
Session session = null;
for(int m =0;m<5;m++){
Admin admin = new Admin();
admin.setName("test");
admin.setPassword("098");
session = this.getSession();
session.save(admin);
}

Only one session will be opened, because transaction control must ensure that it is the same connection, spring will ensure that there is only one session in the entire related method. Spring will open a session at the beginning of the method (even if the transaction control method does not perform database operations), then when requesting the session, if there is an uncommitted session in the transaction, it will return to ensure the same session.

2. getCurrentSession()

With openSession()
The getCurrentSession() and openSession() methods are obtained through Hibernate's SessionFactory. The difference between the two has been introduced in many articles on the Internet, namely: Java code ① The session created by getCurrentSession will be bound to the current thread, while openSession will not. ②The thread created by getCurrentSession will be automatically closed after the transaction is rolled back or the transaction is submitted, and the openSession must be closed manually
① The session created by getCurrentSession will be bound to the current thread, while openSession will not.
②The thread created by getCurrentSession will be automatically closed after the transaction is rolled back or the transaction is submitted, and the openSession must be closed manually


For the getCurrentSession() method:
        (1) Its method must be subject to transaction control
        (2) When the Session is used for the first time, or when getCurrentSession() is called for the first time, its life cycle begins. Then it is bound to the current thread by Hibernate. When the transaction ends, whether it is committed or rolled back, Hibernate will also strip the Session from the current thread and close it. If you call getCurrentSession() again, you will get a new Session and start a new unit of work.
  
For the openSession() method:
         This method is generally not used directly in the integration of spring and Hibernate. It is to open a session, and this session has nothing to do with the context. If you control the transaction in its method, you will find that it does not work. The reason is the aforementioned transaction. The control must ensure the same connection, and the session opened by openSession() has nothing to do with the context. The difference between this method and methods such as getSession(), getCurrentSession() and getHibernateTemplate() is that the latter methods can be controlled by spring. If transaction control is performed on the method in which they are located, spring can ensure the same connection. And the openSession() method, spring cannot control it, so the transaction will not work.

3. OpenSessionInView
The main function of OpenSessionInView is to bind a Hibernate Session to the thread corresponding to a complete request process. Open Session In View keeps the hibernate session in the open state during the request binds the session to the current thread, so that the session can be used throughout the request. For example, in the View layer, PO can also lazy loading data, such as $( company. employees }. After the logic of the View layer is completed, the session will be automatically closed through the doFilter method of the Filter or the postHandle method of the Interceptor.
Java code public class Group implements Serializable{ private int id; private String name; private Set users; ...}
public class Group implements Serializable{
private int id;
private String name;
private Set users;
         ...
}

Load the Group object in the business method and save it to the HttpSession object
Java code List groups = ht.find("from Group"); Group group = (Group)groups.get(0); HttpSession session = ServletActionContext.getRequest().getSession(); session.setAttribute("group", group );
List groups = ht.find("from Group");
Group group = (Group)groups.get(0);
HttpSession session = ServletActionContext.getRequest().getSession();
session.setAttribute("group", group);

Note that Group uses the default lazy loading mechanism, that is, only a Group proxy object is returned at this time.
Display the users attribute of the group object in the jsp page, as follows:

Java code <% Group group = (Group)session.getAttribute("group"); out.println(group.getUsers()); %>
<%
     Group group = (Group)session.getAttribute("group");
     out.println(group.getUsers());
%>

The following exception will be thrown at this time:
Java code org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: entity.Group.users, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: entity.Group.users, no session or session was closed

The delayed loading mechanism makes it only return a proxy object of the Group after the execution of the business method is over. When the value of the group object is used in the jsp page, the SQL statement is issued to load, but the session has been closed at this time. The solution is to use the OpenSessionInView mechanism and configure the following filters in the web.xml page:
Java code <filter> <filter-name>hibernateFilter</filter-name> <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter </filter-class> </filter>
<filter>
   <filter-name>hibernateFilter</filter-name>
   <filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
   </filter-class>
</filter>


to sum up:
(1) For getSession(), getSession(false), getCurrentSession(), and getHibernateTemplate() methods, if you perform transaction control on the method in which it is located, you can ensure that there is only one session in the entire method, no matter how many times you execute it. CRUD operation, and the opened session will be automatically closed at the end of the transaction.
(2) Transaction control must be performed on the method where getSession(false) and getCurrentSession() are located (see the above analysis for reasons)
(3) If there is no transaction control on the method where getSession() and getHibernateTemplate() are located, then if N CRUD operations are performed in the method, N sessions will be opened, that is, every time getSession() and getHibernateTemplate() are called. Open a new session. The difference between these two methods is that the connection is automatically closed when the getHibernateTemplate() method ends, while the getSession() method must be closed manually.
(4) If the openSession() method of SessionFactory is used in the method to obtain a connection for operation, then transaction control cannot be performed on it.
(5) In general development, the getHibernateTemplate() method is usually used for database operations, and the getHibernateTemplate() method uses a template + callback mechanism, which is very convenient for database operations and can be viewed (where the session is opened and closed in the doExecute method ongoing)


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.