Today, when debugging the Dao-layer Singleton of hibernate, the user list is correctly displayed when you refresh the page for the first time on a user overview page. However, when you use F5 to refresh the page, you will find that the user list cannot be correctly displayed, and a hibernate exception is reported. Session is closed! Because I use the one-session-per-request mode, the session should not be closed unless it is committed or closed. I read the code again and did not find such code. When the problem cannot be determined, I can only print the hashcode of the session where the current error is reported, the hashcode of the session where the error is reported is always the same as the hashcode of the session that first enters the page. It is equivalent to using a usermgr (DAO layer) object forever. Taking a closer look at the usermgr object, I use the singleton mode, while the singleton mode only sets the session once, therefore, the session object retrieved from usermgr is the closed session object. Modify the code to get the session used each time from the current thread and solve the error.
Important Notes:
(1) Add the following configuration in hibernate. cfg. XML to set the session to be valid in the current thread.
<! -- Set the context running condition. The value can be JTA/thread/managed. -->
<Property name = "hibernate. current_session_context_class"> thread </property>
(2) One filter of hibernatesessionrequestfilter is used to ensure "one-session-per-request mode"
(3) All Mgr objects (DAO) must inherit from the basehibernatedao class, which provides some basic cud operations.
1. The Code of hibernatesessionrequestfilter is as follows:
/**
* Execute the start and commit of hibernate transaction when providing all JSP access
*
* @ Author Rey
*
*/
Public class hibernatesessionrequestfilter implements filter {
/**
* Logging
*/
Private Static logger = Logger
. Getlogger (hibernatesessionrequestfilter. Class );
Private sessionfactory SF;
/*
* (Non-javadoc)
*
* @ See javax. servlet. Filter # destroy ()
*/
@ Override
Public void destroy (){
SF. Close ();
}
/*
* (Non-javadoc)
*
* @ See javax. servlet. Filter # dofilter (javax. servlet. servletrequest,
* Javax. servlet. servletresponse, javax. servlet. filterchain)
*/
@ Override
Public void dofilter (servletrequest _ Request, servletresponse response,
Filterchain chain) throws ioexception, servletexception {
Try {
SF. getcurrentsession (). begintransaction ();
If (logger. isdebugenabled ()){
Logger
. Debug ("starting a database transaction, session. hashcode ::"
+ SF. getcurrentsession (). hashcode ());
}
// Call the next filter (continue request processing)
Chain. dofilter (_ Request, response );
// Commit and cleanup
If (logger. isdebugenabled ()){
Logger
. Debug ("committing the database transaction, session. hashcode ::"
+ SF. getcurrentsession (). hashcode ());
}
SF. getcurrentsession (). gettransaction (). Commit ();
} Catch (staleobjectstateexception staleex ){
Logger
. Error ("This interceptor does not implement Optimistic Concurrency Control! ");
Logger
. Error ("your application will not work until you add compensation actions! ");
// Rollback, close everything, possibly compensate for any permanent
// Changes
// During the conversation, and finally restart business
// Conversation. Maybe
// Give the user of the application a chance to merge some of his
// Work
// Fresh data... what you do here depends on your applications
// Design.
Throw staleex;
} Catch (throwable ex ){
// Rollback only
Ex. printstacktrace ();
Try {
If (SF. getcurrentsession (). gettransaction (). isactive ()){
Logger
. Debug ("trying to rollback database transaction after exception ");
SF. getcurrentsession (). gettransaction (). rollback ();
}
} Catch (throwable rbex ){
Logger. Error ("cocould not rollback transaction after exception! ",
Rbex );
}
// Let others handle it... maybe another interceptor for exceptions?
Throw new servletexception (Ex );
}
}
/*
* (Non-javadoc)
*
* @ See javax. servlet. Filter # Init (javax. servlet. filterconfig)
*/
@ Override
Public void Init (filterconfig arg0) throws servletexception {
Logger. debug ("Initializing filter ...");
Logger
. Debug ("obtaining sessionfactory from static hibernateutil Singleton ");
Sf = hibernateutil. getsessionfactory ();
}
}
2. The basehibernatedao code is as follows:
/**
* All Mgr classes must inherit abstract classes.
*
* @ Author Rey
*
*/
Public class basehibernatedao <t, Id extends serializable> implements
Ibasehibernatedao <t, Id> {
Private class <t> persistentclass;
Public basehibernatedao (){
// Initialize the object to be persisted Based on the parameter t passed in the generic model. Take the first parameter, which is related to the parameter location of the generic model.
This. persistentclass = (class <t>) (parameterizedtype) getclass ()
. Getgenericsuperclass (). getactualtypearguments () [0];
}
/**
* Obtain the session in the current Mgr. Because MGR is designed as a Singleton, it needs to be obtained from the current thread every time.
*
* @ Return
*/
Protected session getsession (){
// Because it is in singleton mode, you need to obtain it from the current thread every time the session is re-obtained.
Return hibernateutil. getcurrentsession ();
}
Public class <t> getpersistentclass (){
Return persistentclass;
}
@ Suppresswarnings ("unchecked ")
Public t findbyid (ID, Boolean lock ){
T entity;
If (LOCK)
Entity = (t) getsession (). Load (getpersistentclass (), ID,
Lockmode. Upgrade );
Else
Entity = (t) getsession (). Load (getpersistentclass (), ID );
Return entity;
}
@ Suppresswarnings ("unchecked ")
Public list <t> findall (){
Return findbycriteria ();
}
/**
* Query a set based on instance conditions <br>
* Example (inheriting the criteria object) filtering condition to query a specified object set
*
* @ Param exampleinstance
* The object instance of the class to be queried, not XX. Class
* @ Param excludeproperty
* Names of fields not extracted
* @ Return
*/
@ Suppresswarnings ("unchecked ")
Public list <t> findbyexample (T exampleinstance, string [] excludeproperty ){
Criteria crit = getsession (). createcriteria (getpersistentclass ());
Example example = example. Create (exampleinstance );
For (string exclude: excludeproperty ){
Example. excludeproperty (exclude );
}
Crit. Add (example );
Return crit. List ();
}
@ Suppresswarnings ("unchecked ")
Public t makepersistent (T entity ){
Getsession (). saveorupdate (entity );
Return entity;
}
Public void maketransient (T entity ){
Getsession (). Delete (entity );
}
Public void flush (){
Getsession (). Flush ();
}
Public void clear (){
Getsession (). Clear ();
}
/**
* Query a set that meets the filter conditions. <br>
* Criterion: filtering condition <br>
* Criteria: the performer of the filter condition <br>
* Use this inside subclasses as a convenience method.
*/
@ Suppresswarnings ("unchecked ")
Protected list <t> findbycriteria (criterion... criterion ){
Criteria crit = getsession (). createcriteria (getpersistentclass ());
For (criterion C: criterion ){
Crit. Add (C );
}
Return crit. List ();
}
/**
* Query the number of objects. This field and condition are used to calculate the number of objects.
*
* @ Param _ scountselect
* The field to be counted is generally the primary key ID of a persistent object.
* @ Param Criterion
* Filter and count according to certain conditions
* @ Return
* @ Throws myexception
*/
Public int gettotalsize (string _ scountselect, criterion... criterion) throws myexception {
Criteria crit = getsession (). createcriteria (getpersistentclass ());
Crit. setprojection (projections. Count (_ scountselect ));
For (criterion C: criterion ){
Crit. Add (C );
}
Object ototalnumber = crit. uniqueresult ();
If (ototalnumber = NULL ){
Throw new myexception ("error occurred when querying the total number of entries [countselect:" + _ scountselect
+ "]");
}
Return integer. parseint (ototalnumber. tostring ());
}
/**
*
* @ Param _ npageindex
* Query page indexes. The first page starts from 1.
* @ Param _ npagesize
* Number of records displayed on the page
* @ Param _ nitemcoun
* Total number of records
* @ Param _ Criterion
* Query Conditions
* @ Return
*/
Protected list <t> getpageitems (INT _ npageindex, int _ npagesize,
Int _ nitemcoun ){
Criteria crit = getsession (). createcriteria (getpersistentclass ());
// Construct paging Parameters
Mypage currpage = new mypage (_ npagesize );
Currpage. setitemcount (_ nitemcoun );
Currpage. setcurrpageindex (_ npageindex );
// The starting value here is 0, and the starting value of mypage is 1
Crit. setfirstresult (currpage. getfirstitemindex ()-1 );
Crit. setmaxresults (currpage. getcurrpagesize (); // obtain the current page size
Return crit. List ();
}
@ Override
Public list <t> findbyexample (T exampleinstance ){
// Todo auto-generated method stub
Return NULL;
}
}
3. inherit from a Mgr object of the basehibernatedao class, usermgr code:
/**
* The user object business logic management class is only responsible for processing the business logic
*
* @ Author Rey
*
*/
Public class usermgr extends basehibernatedao <user, long> {
/**
* Singleton object
*/
Private Static usermgr m_singlemgr = NULL;
/**
* Singleton Method
*
* @ Return
*/
Public static usermgr getinstance (){
If (m_singlemgr = NULL ){
M_singlemgr = new usermgr ();
}
Return m_singlemgr;
}
// Constructor
Public usermgr (){
Super ();
}
/**
* Getting user objects based on user IDs
*
* @ Param _ luserid
* User ID
* @ Return
* @ Throws myexception
*/
Public user findbyid (long _ luserid ){
Return (User) Super. findbyid (_ luserid, false );
}
// Provide external query functions ============================
/**
* Save the user to the database, including adding and modifying the user
*
* @ Param _ saveuser
* Users to save
* @ Return
* @ Throws myexception
*/
Public user saveorupdate (User _ saveuser) throws myexception {
If (_ saveuser = NULL)
Throw new myexception ("the saved user object is null! ");
Return (User) This. makepersistent (_ saveuser );
}
/**
* Delete a user
*
* @ Param _ deleteuser
* User object to be deleted
* @ Throws myexception
*/
Public void Delete (User _ deleteuser) throws myexception {
If (_ deleteuser = NULL)
Throw new myexception ("the user object to be deleted is null! ");
This. maketransient (_ deleteuser );
}
/**
* Deletes the user information of a specified IDs and returns the number of deleted users.
*
* @ Param _ sdeleteuserids
* @ Throws myexception
*/
Public int Delete (string _ sdeleteuserids) throws myexception {
// 1. If SQL is used for deletion, the cache may be faulty.
// 2. If one row is deleted, performance problems may occur. Batch deletion is considered.
If (_ sdeleteuserids = NULL ){
Return 0;
}
Stringbuilder sbhql = new stringbuilder (
"Delete from user where userid in (? ");
String [] auserids = _ sdeleteuserids. Split (",");
For (INT I = 1; I <auserids. length; I ++ ){
Sbhql. append (",? ");
}
Sbhql. append (")");
// Construct a query
Query deletequery = getsession (). createquery (sbhql. tostring ());
// Add Parameters
For (INT I = 0; I <auserids. length; I ++ ){
Deletequery. setstring (I, auserids [I]);
}
Return deletequery.exe cuteupdate ();
}
/**
*
* @ Param _ npageindex
* Query page indexes. The first page starts from 1.
* @ Param _ npagesize
* Number of page records
*
* @ Param _ nitemcount
* Total number of page records
* @ Return
*/
Public list <user> getpageusers (INT _ npageindex, int _ npagesize,
Int _ nitemcount ){
Return this. getpageitems (_ npageindex, _ npagesize, _ nitemcount );
}
}