Hallo,
ein HibernateSessionFilter (HSF) zu verwenden ist grundsätzlich eine gute Idee!
Allerdings habe ich ein paar Anmerkungen, was man meiner Meinung nach vielleicht besser machen könnte (hängt natürlich auch vom Sinn und Zweck der gesamten Applikation ab).
1) Im HSF würde ich weder eine Session auf machen noch eine Transaction, denn was ist wenn es Aktionen gibt (z.b: nur selects) die gar keine Transaction oder gar Sessions (z.b: forwards auf andere Webseiten) benötigen.
2) Wenn ich den Code des HSF richtig lese, wird im Fehlerfall zwar die Transaction aufgelöst, aber nicht die Session geschlossen, dies könnte die Datenbank mit zuvielen offenen Sessions belasten bzw. blockieren.
3) Statt des c3p0 könnte das Connection-Pooling von apache verwendet werden (commons-dbcp und commons-pool jars ins common/lib Verzeichnis von Tomcat kopieren). c3p0 hat in bestimmten Fällen (max. erlaubte Session Anzahl der DB überschritten) meiner Meinung nach kein korrektes Logging bzw. Verhalten.
Ich mache also folgendes:
Im HSF:
Code:
public final class HibernateSessionFilter implements Filter {
static Log logger = LogFactory.getLog(HibernateSessionFilter.class);
/**
* @see javax.servlet.Filter.destroy()
*/
public void destroy() {
}
/**
* @see javax.servlet.Filter.init()
*/
public void init(FilterConfig arg0) throws ServletException {
}
/**
* Time the processing that is performed by all subsequent filters in the
* current filter stack, including the ultimately invoked servlet.
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
// Pass control on to the next filter
chain.doFilter(request, response);
} finally {
try {
HibernateUtil.closeSession();
logger.debug("session closed!");
} catch (Exception e) {
logger.warn("closeSession failed! : " + e.getMessage());
}
}
}
/**
* Return a String representation of this object.
*/
public String toString() {
return this.getClass().getName();
}
}
im HibernateUtil:
Code:
public class HibernateUtil {
static Log log = LogFactory.getLog(HibernateUtil.class);
static ThreadLocal<Session> session = new ThreadLocal<Session>();
private static SessionFactory factory = null;
/** Creates a new instance of HibernateUtil */
public HibernateUtil() {
}
private static void getFactory() throws HibernateException {
if (factory == null) {
factory = new Configuration().configure().buildSessionFactory();
}
}
private static void getFactoryJNDI() throws NamingException, HibernateException {
if (factory == null) {
factory = (SessionFactory) new InitialContext().lookup("java:comp/env/hibernate/SessionFactory");
}
}
public static Session openSession() throws NotFoundException {
Session s = (Session) session.get();
try {
if (s == null) {
// Don't get from JNDI, use a static SessionFactory
if (factory == null) {
try {
getFactoryJNDI();
} catch (Exception e) {
//e.printStackTrace();
getFactory();
}
}
s = factory.openSession();
session.set(s);
}
} catch (HibernateException ne) {
throw new NotFoundException(ne.getMessage(), ne);
}
return s;
}
public static void closeSession() {
Session s = (Session) session.get();
session.set(null);
if (s != null) {
try {
s.close();
} catch (HibernateException he) {
log.warn(he.getMessage());
if (log.isDebugEnabled()) log.debug(he.getMessage(), he);
}
}
}
}
in einer DAO-Klasse kommt z.b: folgende Methode zum Einsatz:
Code:
public static void updateAttribute(Long attributeId, AttributeForm attributeForm, User user) throws Exception {
Session session = HibernateUtil.openSession();
Attribute attribute = (Attribute)session.load(Attribute.class, attributeId);
if(!user.testPermissionFlag(User.PERMISSION_MANAGE_ATTRIBUTES))
throw new PermissionException("User is not allowed to manage attributes!");
Transaction tx = session.beginTransaction();
try {
//Attributwerte mit attributeForm updaten
tx.commit();
} finally {
if (tx != null && tx.isActive()) tx.rollback();
}
}
relevante Teile des hibernate.cfg.xml:
Code:
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://XXXXXXX</property>
<property name="connection.username">XXXX</property>
<property name="connection.password">XXXX</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.max_fetch_depth">1</property>
<property name="hibernate.cglib.use_reflection_optimizer">true</property>
Hoffe damit ein paar interessante Anregungen gegeben zu haben,
Gruß scheer4711