-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Best Practices - Where to do Session creation?
PostPosted: Wed Feb 25, 2004 4:54 pm 
Newbie

Joined: Fri Oct 17, 2003 11:31 am
Posts: 19
I've got a question regarding the best practices for where to do Session creation?


The way I currently have the architecture setup is to have my Action classes (I'm using struts) call to a Manager layer (something like MemberManager). Within this layer is where all of the sessions are created for interacting with the DB. So I have a method called MemberManager.retrieveMember(long memberId).

This seems to work well, this allows me to localize where the Sessions are being created and flushed. This also encapsulates this logic so that my calling struts Action class doesn't need to worry about getting a Session from the SessionFactory, and can just hand off the object that needs to be persisted.

The one problem I will be running into using the structure is when I try to lazy-instantiate my collections. Since I can't access the collections without having an open Session, I'm going to be in trouble.

Has anyone run across this issue, and is it deemed 'good coding' to actually just grab a Session and flush it from within the Controller layer of MVC?

I could easily do the following, but I'm still hung up on the fact that the Controller layer shouldn't be directly calling the DB :

Code:
Session session = factory.openSession();
Team team = (Team) session.find("from team in class example.Team where team.city = ?",        cityName, Hibernate.STRING).get(0);
Set players = team.getPlayers();
Player p = (Player) players.get(0);
session.close();


Any help or suggestions of what you have done, or if there is a 'best practices' approach for how to do this, would be greatly appreciated.

Thanks in advance,

Quenten


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 25, 2004 5:26 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
try to use threadlocal session + a servlet filter.
The thread local session "attach" a session on the currect thread, this mean that all is done in a request (action) use the same Session, the filter manage the connection/disconnection of the session and will clean the thread local when the action is done.

i also use struts and this is the best practice.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 25, 2004 5:41 pm 
Newbie

Joined: Fri Oct 17, 2003 11:31 am
Posts: 19
Do you by chance have some code snippets I could look at? A snippet of code from the Action servlet, as well as the filter code?

I'm a little confused as to what the threadlocal is, as well as how to attach a Session to the local thread.

Thanks,

Quenten


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 25, 2004 5:49 pm 
Hibernate Team
Hibernate Team

Joined: Thu Dec 18, 2003 9:55 am
Posts: 1977
Location: France
http://www.hibernate.org/43.html



package org.infohazard.pig.servlet;

import java.io.*;
import javax.servlet.*;
import javax.naming.*;

import net.sf.hibernate.*;

/**
* Filter which manages a ThreadLocal hibernate session. Obtain the session
* by calling Persistance.getSession(). Define the JNDI name of the
* hibernate session factory as an init param to the filter in your web.xml.
*
* @author <a href="mailto:jeff@infohazard.org">Jeff Schnitzer</a>
*/
public class Persistance implements Filter
{
/**
* Filter init param which defines the JNDI name for the hibernate factory
*/
public static final String HIBERNATE_FACTORY_JNDI_PARAM = "hibernateFactory";

/**
* Default value if no init param is set.
*/
public static final String HIBERNATE_FACTORY_JNDI_DEFAULT = "java:/HibernateSessionFactory";

/**
* Holds the current hibernate session, if one has been created.
*/
protected static ThreadLocal hibernateHolder = new ThreadLocal();

/**
*/
protected static SessionFactory factory;

/**
*/
public void init(FilterConfig filterConfig) throws ServletException
{
// Initialize hibernate
try
{
new Configuration().configure();
}
catch (HibernateException ex) { throw new ServletException(ex); }

// As good a place as any to initialize the factory
String factoryJndiName = filterConfig.getInitParameter(HIBERNATE_FACTORY_JNDI_PARAM);
if (factoryJndiName == null)
factoryJndiName = HIBERNATE_FACTORY_JNDI_DEFAULT;

try
{
Context ctx = new InitialContext();
factory = (SessionFactory)ctx.lookup(factoryJndiName);
}
catch (NamingException ex) { throw new ServletException(ex); }
}

/**
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
if (hibernateHolder.get() != null)
throw new IllegalStateException(
"A session is already associated with this thread! "
+ "Someone must have called getSession() outside of the context "
+ "of a servlet request.");

try
{
chain.doFilter(request, response);
}
finally
{
Session sess = (Session)hibernateHolder.get();
if (sess != null)
{
hibernateHolder.set(null);

try
{
sess.close();
}
catch (HibernateException ex) { throw new ServletException(ex); }
}
}
}

/**
* ONLY ever call this method from within the context of a servlet request
* (specifically, one that has been associated with this filter). If you
* want a Hibernate session at some other time, call getSessionFactory()
* and open/close the session yourself.
*
* @return an appropriate Session object
*/
public static Session getSession() throws HibernateException
{
Session sess = (Session)hibernateHolder.get();

if (sess == null)
{
sess = factory.openSession();
hibernateHolder.set(sess);
}

return sess;
}

/**
* @return the hibernate session factory
*/
public static SessionFactory getSessionFactory()
{
return factory;
}

/**
* This is a simple method to reduce the amount of code that needs
* to be written every time hibernate is used.
*/
public static void rollback(Transaction tx)
{
if (tx != null)
{
try
{
tx.rollback();
}
catch (HibernateException ex)
{
// Probably don't need to do anything - this is likely being
// called because of another exception, and we don't want to
// mask it with yet another exception.
}
}
}

/**
*/
public void destroy()
{
// Nothing necessary
}
}

just declare the filter in your web.xml
if you have problem with jndi, modify SessionFactory sf = (SessionFactory) new InitialContext().lookup("SessionFactory")... send me a mail, i'm not at work now.

The methods are static so just call getSession() everywhere you want in a httpcontext.

Once you've done it, ... the most complicated is done in term of managing session, 1 session per httprequest (action) cover 99% of the webapp.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.