I am using
hibernate 2.1
mysql
c3p0 to manage connection pool
Hi,
I am using the hibernate plugin in my struts webapp. I am using some code that I found in a struts polls app:
public final class HibernatePlugIn extends SetupDAO{
/**
* The <code>Log</code> instance for this class.
*/
private static Log log = LogFactory.getLog( HibernatePlugIn.class );
public static int numberSessions;
/**
* Reference to our SessionFactory. Can close and dispose if not null.
*/
private static SessionFactory sf;
public static final ThreadLocal session = new ThreadLocal();
public void init(ActionServlet servlet, ModuleConfig config)
throws ServletException {
super.init( servlet, config );
if (sf == null){
try {
sf = createConfiguration().buildSessionFactory();
if (log.isInfoEnabled()){
log.info(" Initializing Hibernate plugIn");
}
}catch (HibernateException he) {
if (log.isErrorEnabled()){
log.error(" Unable to create session factory from configuration", he);
}
throw new ServletException(" Unable to create session factory from configuration", he);
}
}
if (log.isInfoEnabled()){
log.info(" Hibernate plugIn initialized");
}
}
/**
* Return the SessionFactory.
* @return The SessionFactory for this application session
* @throws HibernateException if an error occurs
*/
public static SessionFactory sessionFactory()
throws HibernateException {
return sf;
}
/**
* The classes with mappings to add to the Configuration are enumerated here.
* There should be a "${class}.hbm.xml" mapping file for each class
* stored with each compiled class file.
* <p>
* To complete the Hibernate setup, there must be a valid "hibernate.properties"
* file under the "classes" folder (root of the classpath),
* which specifies the details of the database hookup.
* <p>
* The mapping documents and properties file is all that Hibernate requires.
* <p>
* @return A Configuration object
* @throws net.sf.hibernate.MappingException if any the mapping documents can't
* be rendered.
*/
private static final Configuration createConfiguration()
throws MappingException {
if (log.isInfoEnabled()){
log.info(" Loading Hibernate plugIn configuration");
}
return new Configuration()
.addClass(uk.co.ritmos.Title.class)
.addClass(uk.co.ritmos.Genre.class)
.addClass(uk.co.ritmos.Subgenre.class)
.addClass(uk.co.ritmos.User.class)
.addClass(uk.co.ritmos.Plan.class)
.addClass(uk.co.ritmos.Age.class)
.addClass(uk.co.ritmos.Watch.class)
.addClass(uk.co.ritmos.Feedback.class)
.addClass(uk.co.ritmos.Condition.class)
.addClass(uk.co.ritmos.Sale.class)
.addClass(uk.co.ritmos.Track.class)
.addClass(uk.co.ritmos.Format.class)
.addClass(uk.co.ritmos.Wish.class)
.addClass(uk.co.ritmos.Shipping.class)
.addClass(uk.co.ritmos.Help.class);
}
public void destroy() {
super.destroy();
if (null != sf) {
try {
sf.close();
} catch (HibernateException he) {
if (log.isErrorEnabled()){
log.error(" Unable to release hibernate resources", he);
}
}
}
sf = null;
if (log.isInfoEnabled()){
log.info(" Hibernate plugIn resources released");
}
}
public static void shutdown(){
if (null != sf) {
try {
sf.close();
} catch (HibernateException he) {
if (log.isErrorEnabled()){
log.error(" Unable to release resources", he);
}
}
}
sf = null;
if (log.isInfoEnabled()){
log.info(" Hibernate plugIn resources released");
}
}
/**
* Closes an hibernate {@link Session}, releasing its resources.
* @throws HibernateException if an hibernate error occurs
* @throws SQLException if an SQL error occurs
*/
public static void closeSession()
throws HibernateException, SQLException{
Session s = (Session) session.get();
session.set( null );
if (s != null) {
s.close();
numberSessions -= 1;
}
}
/**
* Returns an hibernate {@link Session} from the session factory.
* @return an hibernate {@link Session}
* @throws Exception if an error occurs
*/
public static Session openSession()
throws Exception{
Session s = (Session) session.get();
if (s == null){
s = sf.openSession();
session.set( s );
numberSessions += 1;
}
return (s);
}
}
(amended from the original by Jorge Basto)
Now, I am doing all my database retrieval and persistance using
openSession();
...
do something
...
closeSession();
Now, I understand what a session is for, but what I am worried about is the case where I may forget to close a session for whatever reason in my code. The session holds up (orphans) a database connection, and does not timeout according to the hibernate cp30 timeout parameter. This happens several times (to the size of my connection pool), and the whole application locks up.
What I want to know is:
(a) is it compulsory to close the session to avoid leaking connections?
(b) is there a way to kill the session automatically after the timeout has been reached?
(c) are there any best practices that you can share with me?
Many thanks, al
|