Hi,
I am using Hiberante 3.2 together with Struts-1.3.5. I am trying to create a web application which uses the DAO pattern.
I based most of my code from
http://www.hibernate.org/328.html
GenericDAO
Code:
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
public interface GenericDAO<T, ID extends Serializable> {
T findById(ID id, boolean lock) throws DataAccessException;
Collection<T> findAll() throws DataAccessException;
List<T> findByExample(T exampleInstance, String[] excludeProperty) throws DataAccessException;
T makePersistent(T entity) throws DataAccessException;
void makeTransient(T entity) throws DataAccessException;
/**
* Affects every managed instance in the current persistence context!
*/
void flush();
/**
* Affects every managed instance in the current persistence context!
*/
void clear();
}
DAOFactory:
Code:
/**
* Defines all DAOs and the concrete factories to get the conrecte DAOs.
* <p>
* To get a concrete DAOFactory, call <tt>instance()</tt> with one of the
* classes that extend this factory.
* <p>
* Implementation: If you write a new DAO, this class has to know about it.
* If you add a new persistence mechanism, add an additional concrete factory
* for it as a constant, like <tt>HIBERNATE</tt>.
*/
public abstract class DAOFactory {
/**
* Creates a standalone DAOFactory that returns unmanaged DAO
* beans for use in any environment Hibernate has been configured
* for. Uses HibernateUtil/SessionFactory and Hibernate context
* propagation (CurrentSessionContext), thread-bound or transaction-bound,
* and transaction scoped.
*/
public static final Class HIBERNATE = com.softamo.libamo.common.HibernateDAOFactory.class;
/**
* Factory method for instantiation of concrete factories.
*/
public static DAOFactory instance(Class factory) {
try {
return (DAOFactory)factory.newInstance();
} catch (Exception ex) {
throw new RuntimeException("Couldn't create DAOFactory: " + factory);
}
}
// Add your DAO interfaces here
public abstract LinksDAO getLinksDAO();
}
HibernateDAOFactory
Code:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import hibernate.HibernateUtil;
import links.LinksDAO;
import links.LinksVO;
public class HibernateDAOFactory extends DAOFactory {
private static Log log = LogFactory.getLog(HibernateDAOFactory.class);
public LinksDAO getLinksDAO() {
return (LinksDAO)instantiateDAO(LinksDAOHibernate.class);
}
private GenericHibernateDAO instantiateDAO(Class daoClass) {
try {
log.debug("Instantiating DAO: " + daoClass);
return (GenericHibernateDAO)daoClass.newInstance();
} catch (Exception ex) {
throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
}
}
// You could override this if you don't want HibernateUtil for lookup
protected Session getCurrentSession() {
return HibernateUtil.getSessionFactory().getCurrentSession();
}
// Inline concrete DAO implementations with no business-related data access methods.
// If we use public static nested classes, we can centralize all of them in one source file.
public static class LinksDAOHibernate
extends GenericHibernateDAO<LinksVO, Long>
implements LinksDAO {}
}
GenericHibernateDAO
Code:
package com.softamo.libamo.common;
import com.softamo.libamo.hibernate.HibernateUtil;
import org.hibernate.*;
import org.hibernate.criterion.*;
import java.util.*;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
/**
* Implements the generic CRUD data access operations using Hibernate APIs.
* <p>
* To write a DAO, subclass and parameterize this class with your persistent class.
* Of course, assuming that you have a traditional 1:1 appraoch for Entity:DAO design.
* <p>
* You have to inject a current Hibernate <tt>Session</tt> to use a DAO. Otherwise, this
* generic implementation will use <tt>HibernateUtil.getSessionFactory()</tt> to obtain the
* curren <tt>Session</tt>.
*
* @see HibernateDAOFactory
*
* @author Christian Bauer
*/
public abstract class GenericHibernateDAO<T, ID extends Serializable>
implements GenericDAO<T, ID> {
private Class<T> persistentClass;
private Session session;
public GenericHibernateDAO() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
public void setSession(Session s) {
this.session = s;
}
protected Session getSession() {
if (session == null)
session = HibernateUtil.getSessionFactory().getCurrentSession();
return session;
}
public Class<T> getPersistentClass() {
return persistentClass;
}
@SuppressWarnings("unchecked")
public T findById(ID 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();
}
@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();
}
/**
* 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();
}
}
DataAccessObject
Code:
/*
* DataAccessObject.java
*
* Created on August 24, 2002, 5:23 PM
*/
package com.softamo.libamo.common;
import java.util.Collection;
public interface DataAccessObject {
public ValueObject findByPK(String primaryKey, boolean lock) throws DataAccessException;
public Collection findAll() throws DataAccessException;
public void insert(ValueObject insertRecord) throws DataAccessException;
public void update(ValueObject updateRecord) throws DataAccessException;
public void delete(ValueObject deleteRecord) throws DataAccessException;
}
The HiberanteUtil class comes from the CaveatEmptor example application and is shown below:
Code:
import org.hibernate.*;
import org.hibernate.cfg.*;
import org.apache.commons.logging.*;
import javax.naming.*;
/**
* Basic Hibernate helper class for Hibernate configuration and startup.
* <p>
* Uses a static initializer to read startup options and initialize
* <tt>Configuration</tt> and <tt>SessionFactory</tt>.
* <p>
* This class also tries to figure out if JNDI binding of the <tt>SessionFactory</tt>
* is used, otherwise it falls back to a global static variable (Singleton). If
* you use this helper class to obtain a <tt>SessionFactory</tt> in your code,
* you are shielded from these deployment differences.
* <p>
* Another advantage of this class is access to the <tt>Configuration</tt> object
* that was used to build the current <tt>SessionFactory</tt>. You can access
* mapping metadata programmatically with this API, and even change it and rebuild
* the <tt>SessionFactory</tt>.
* <p>
* Note: This class supports annotations if you replace the line that creates
* a Configuration object.
* <p>
* Note: This class supports only one data store. Support for several
* <tt>SessionFactory</tt> instances can be easily added (through a static <tt>Map</tt>,
* for example). You could then lookup a <tt>SessionFactory</tt> by its name.
*
* @author Christian Bauer
*/
public class HibernateUtil {
//private static Log log = LogFactory.getLog(HibernateUtil.class);
private static Configuration configuration;
private static SessionFactory sessionFactory;
static {
// Create the initial SessionFactory from the default configuration files
try {
//log.debug("Initializing Hibernate");
// Read hibernate.properties, if present
configuration = new Configuration();
// Use annotations: configuration = new AnnotationConfiguration();
// Read hibernate.cfg.xml (has to be present)
configuration.configure();
// Build and store (either in JNDI or static variable)
rebuildSessionFactory(configuration);
//log.debug("Hibernate initialized, call HibernateUtil.getSessionFactory()");
} catch (Throwable ex) {
// We have to catch Throwable, otherwise we will miss
// NoClassDefFoundError and other subclasses of Error
//log.error("Building SessionFactory failed.", ex);
throw new ExceptionInInitializerError(ex);
}
}
/**
* Returns the Hibernate configuration that was used to build the SessionFactory.
*
* @return Configuration
*/
public static Configuration getConfiguration() {
return configuration;
}
/**
* Returns the global SessionFactory either from a static variable or a JNDI lookup.
*
* @return SessionFactory
*/
public static SessionFactory getSessionFactory() {
String sfName = configuration.getProperty(Environment.SESSION_FACTORY_NAME);
if ( sfName != null) {
//log.debug("Looking up SessionFactory in JNDI");
try {
return (SessionFactory) new InitialContext().lookup(sfName);
} catch (NamingException ex) {
throw new RuntimeException(ex);
}
} else if (sessionFactory == null) {
rebuildSessionFactory();
}
return sessionFactory;
}
/**
* Closes the current SessionFactory and releases all resources.
* <p>
* The only other method that can be called on HibernateUtil
* after this one is rebuildSessionFactory(Configuration).
*/
public static void shutdown() {
//log.debug("Shutting down Hibernate");
// Close caches and connection pools
getSessionFactory().close();
// Clear static variables
sessionFactory = null;
}
/**
* Rebuild the SessionFactory with the static Configuration.
* <p>
* Note that this method should only be used with static SessionFactory
* management, not with JNDI or any other external registry. This method also closes
* the old static variable SessionFactory before, if it is still open.
*/
public static void rebuildSessionFactory() {
//log.debug("Using current Configuration to rebuild SessionFactory");
rebuildSessionFactory(configuration);
}
/**
* Rebuild the SessionFactory with the given Hibernate Configuration.
* <p>
* HibernateUtil does not configure() the given Configuration object,
* it directly calls buildSessionFactory(). This method also closes
* the old static variable SessionFactory before, if it is still open.
*
* @param cfg
*/
public static void rebuildSessionFactory(Configuration cfg) {
//log.debug("Rebuilding the SessionFactory from given Configuration");
if (sessionFactory != null && !sessionFactory.isClosed())
sessionFactory.close();
if (cfg.getProperty(Environment.SESSION_FACTORY_NAME) != null) {
//log.debug("Managing SessionFactory in JNDI");
cfg.buildSessionFactory();
} else {
//log.debug("Holding SessionFactory in static variable");
sessionFactory = cfg.buildSessionFactory();
}
configuration = cfg;
}
}
This are my Links classes:
LinksDAO
Code:
import com.softamo.libamo.common.GenericDAO;
public interface LinksDAO extends GenericDAO<LinksVO, Long> {
}
LinksVO:
Code:
package com.softamo.libamo.links;
import com.softamo.libamo.common.ValueObject;
public class LinksVO extends ValueObject implements java.io.Serializable {
// Fields
private long linksId;
private String label;
private String url;
private String title;
private String description;
// Constructors
/** default constructor */
public LinksVO() {
}
/** full constructor */
public LinksVO(String label, String url, String title, String description) {
this.label = label;
this.url = url;
this.title = title;
this.description = description;
}
// Property accessors
public long getLinksId() {
return this.linksId;
}
protected void setLinksId(long linksId) {
this.linksId = linksId;
}
public String getLabel() {
return this.label;
}
public void setLabel(String label) {
this.label = label;
}
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return this.description;
}
public void setDescription(String description) {
this.description = description;
}
}
This is my Links Struts action class:
Code:
import java.util.Collection;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.MappingDispatchAction;
import org.apache.struts.validator.DynaValidatorForm;
import com.softamo.libamo.common.DAOFactory;
import com.softamo.libamo.common.DataAccessException;
import com.softamo.libamo.hibernate.HibernateUtil;
import com.softamo.libamo.links.LinksDAO;
import com.softamo.libamo.links.LinksVO;
public class LinksPageAction extends MappingDispatchAction {
@SuppressWarnings("finally")
public ActionForward add(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
DynaValidatorForm dynaform = (DynaValidatorForm) form;
LinksVO link = new LinksVO();
link.setLabel(dynaform.getString("label"));
link.setUrl(dynaform.getString("url"));
link.setTitle(dynaform.getString("title"));
try {
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
LinksDAO dao = factory.getLinksDAO();
dao.makePersistent(link);
HibernateUtil.getSessionFactory().getCurrentSession()
.getTransaction().commit();
} catch (DataAccessException ex) {
// Rethrow as a checked exception
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
return (mapping.findForward("system.error"));
} finally {
HibernateUtil.getSessionFactory().getCurrentSession().close();
return mapping.findForward("linkspage.success");
}
}
@SuppressWarnings("finally")
public ActionForward update(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
try {
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
DynaValidatorForm dynaform = (DynaValidatorForm) form;
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
LinksDAO dao = factory.getLinksDAO();
LinksVO link = dao.findById(Long.valueOf(dynaform.get("linksId").toString()),true);
link.setLabel(dynaform.get("label").toString());
link.setUrl(dynaform.get("url").toString());
link.setTitle(dynaform.get("title").toString());
HibernateUtil.getSessionFactory().getCurrentSession()
.getTransaction().commit();
} catch (DataAccessException ex) {
// Rethrow as a checked exception
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
return (mapping.findForward("system.error"));
} finally {
HibernateUtil.getSessionFactory().getCurrentSession().close();
return mapping.findForward("linkspage.success");
}
}
@SuppressWarnings("finally")
public ActionForward remove(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
try { HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
LinksDAO dao = factory.getLinksDAO();
LinksVO link = dao.findById(Long.valueOf(request.getParameter("linksId")),true);
dao.makeTransient(link);
HibernateUtil.getSessionFactory().getCurrentSession()
.getTransaction().commit();
} catch (DataAccessException ex) {
// Rethrow as a checked exception
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
return (mapping.findForward("system.error"));
} finally {
HibernateUtil.getSessionFactory().getCurrentSession().close();
return mapping.findForward("linkspage.success");
}
}
@SuppressWarnings("finally")
public ActionForward findAll(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
try {
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
LinksDAO dao = factory.getLinksDAO();
Collection links_set = dao.findAll();
request.setAttribute("Links", links_set);
} catch (DataAccessException ex) {
// Rethrow as a checked exception
HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
return (mapping.findForward("system.error"));
} finally {
HibernateUtil.getSessionFactory().getCurrentSession().close();
return mapping.findForward("linkspage.success");
}
}
@SuppressWarnings("finally")
public ActionForward find(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception
{
try {
HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
DAOFactory factory = DAOFactory.instance(DAOFactory.HIBERNATE);
LinksDAO dao = factory.getLinksDAO();
LinksVO link = (LinksVO) dao.findById(Long.valueOf(request.getParameter("linksId")), true);
request.setAttribute("Link", link);
} catch (DataAccessException ex) {
// Rethrow as a checked exception
HibernateUtil.getSessionFactory().getCurrentSession()
.getTransaction().rollback();
return (mapping.findForward("system.error"));
} finally {
HibernateUtil.getSessionFactory().getCurrentSession().close();
return mapping.findForward("linkspage.success");
}
}
}
Apparently my code is working good but my Web application is crashing after some hours. It seems is leaving some MySQL threads opened or something like this. Can anyone point me to a solution, i have defenitely no idea what i am doing wrong?