viernes, 13 de marzo de 2009

Recuperar sesiones hibernate con c3po

Hola:

Hace un par de días me encontré con un problema con hibernate ocupando en pool mi clase anterior era esta.

package org.util;

/
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

/**
*
* @author mew
*/
public class SessionFactorySingleton {
private static SessionFactory sf = null;
/**
* crea una sesion que utiliza todo el programa
*/
private SessionFactorySingleton(){
}
public static SessionFactory getSessionFactory(){
if(sf == null){
sf = new Configuration().configure().buildSessionFactory();
}

return sf;
}
}

Pero lo que pasaba esque el pool de c3po no administraba bien las conexiones, y en un blog encontre este conexion

package org.util;

/**
*
* @author isaac
*/

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;

/**
* Configures and provides access to Hibernate sessions, tied to the
* current thread of execution. Follows the Thread Local Session
* pattern, see {@link http://hibernate.org/42.html }.
*/
public class SessionFactory {

/**
* Location of hibernate.cfg.xml file.
* Location should be on the classpath as Hibernate uses
* #resourceAsStream style lookup for its configuration file.
* The default classpath location of the hibernate config file is
* in the default package. Use #setConfigFile() to update
* the location of the configuration file for the current session.
*/
private static String CONFIG_FILE_LOCATION = "hibernate.cfg.xml";
private static final ThreadLocal threadLocal = new ThreadLocal();
private static Configuration configuration = new Configuration();
private static org.hibernate.SessionFactory sessionFactory;
private static String configFile = CONFIG_FILE_LOCATION;

private SessionFactory() {
}

/**
* Returns the ThreadLocal Session instance. Lazy initialize
* the SessionFactory if needed.
*
* @return Session
* @throws HibernateException
*/
public static Session getSession() throws HibernateException {
Session session = (Session) threadLocal.get();

if (session == null || !session.isOpen()) {
System.out.println("<<<<<<<<<>>>>>>>");
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
}

return session;
}

/**
* Rebuild hibernate session factory
*
*/
public static void rebuildSessionFactory() {
try {
configuration.configure(configFile);
sessionFactory = configuration.buildSessionFactory();
} catch (Exception e) {
System.err
.println("%%%% Error Creating SessionFactory %%%%");
e.printStackTrace();
}
}

/**
* Close the single hibernate session instance.
*
* @throws HibernateException
*/
public static void closeSession() throws HibernateException {
Session session = (Session) threadLocal.get();
threadLocal.set(null);

if (session != null) {
session.close();
}
}

/**
* return session factory
*
*/
public static org.hibernate.SessionFactory getSessionFactory() {
return sessionFactory;
}

/**
* return session factory
*
* session factory will be rebuilded in the next call
*/
public static void setConfigFile(String configFile) {
SessionFactory.configFile = configFile;
sessionFactory = null;
}

/**
* return hibernate configuration
*
*/
public static Configuration getConfiguration() {
return configuration;
}

}

Esta conexion es mucho mas eficiente y con la ayuda de c3po ayuda bastante.

Mi configuracion de C3PO es la siguiente:

<property name="hibernate.c3p0.acquire_increment">1</property>

<property name="hibernate.c3p0.idle_test_period">120</property>

<property name="hibernate.c3p0.timeout">180</property>

<property name="hibernate.c3p0.max_size">20</property>

<property name="hibernate.c3p0.min_size">0</property>

<property name="hibernate.c3p0.max_statements">0</property>

<property name="hibernate.c3p0.preferredTestQuery">select 1;</property>




Le puse en 0 hibernate.c3p0.min_size porque aquí donde trabajo se ponen locos si ven una conexión mucho tiempo, pero ustedes deben hacer sus pruebas, dependiendo de muchos factores:

* Su mapeo de hibernate (contiene muchos Many-to-Many,lazy,ect)
* El hql,o sql mas pesado, de su proyecto,para saber el costo de su qury pueden ocupar en oracle esto:

explain plan for SELECT campos FROM tabla
y para ver el peso del query select * from plan_table

* Tomar el tiempo del Query mas pesado.

En los controles, contenedores, cerrar las conexiones este es muy importante.

2 comentarios:

Anónimo dijo...

Hola. He probado tu ejemplo y tiene un grave problema. Cuando tienes logeados ,por ejemplo, 5 usuarios las sesiones se mezclan. Por lo que un usuario ve los datos que esta cargando otro. C3PO se encarga de cerrar las sesiones? Porque me puede estar pasando esto? Muchas gracias!!

David dijo...

Hola Amigo , podrias compartir como manejas el Objeto Session desde cada clase mapeada, con tu metodo , Gracias