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.  [ 6 posts ] 
Author Message
 Post subject: my DAO is broken, anyone have one that works?
PostPosted: Sat Aug 19, 2006 8:14 pm 
Beginner
Beginner

Joined: Sat Aug 19, 2006 8:04 pm
Posts: 30
hi, i'm using hibernate and it is one of the best things ever. the other guys at work spend so much time dealing with databases, i don't even think about it much at all.

anyways, i'm having some problems with my DAO. specifically, i'm getting non-unique object, transient object, session is closed, (among others) exceptions pretty much at random.

i bought the book hibernate quickly, i'm using what i got from there (pretty much) in a webapp. i'm wondering if someone can either tell me what i'm doing wrong, or better yet just post up a DAO that they've been using that doesn't cause exceptions.

what about using spring to handle all this? really i'm kind of upset i have to write and maintain this code, it would be nice if hibernate did all this for me, and just gave me a simple API, saveUpdate(), delete(), read(), readAll(). i think something like that would be very sensible, i'm not sure why the burden of handling sessions and all this crap below is forced on the user.

here's my broke ass DAO

Code:
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.Query;
import java.io.Serializable;

import java.util.List;

/**
* A layer supertype that handles the common operations for all Data Access Objects.
*/
public class DAO<T, PK extends Serializable> implements GenericDAO<T, PK> {

        private Session session;
        private Transaction tx;
        private Class<T> type;

        public DAO(Class<T> type) {
                this.type = type;
        }

        @SuppressWarnings("unchecked")
        public PK create(T o) {
                Serializable pk = null;
                try {
                        startOperation();
                        pk = session.save(o);
                        tx.commit();
                } catch (HibernateException e) {
                        handleException(e);
                }
                return (PK)pk;
        }

        @SuppressWarnings("unchecked")
        public T read(PK id) {
                T o = null;
                try {
                        startOperation();
                        o = (T) session.load(type, id);
                        tx.commit();
                } catch (HibernateException e) {
                        handleException(e);
                }
                return o;
        }

        public void saveOrUpdate(T o)  {
                try {
                        startOperation();
        //              session.clear();
                        session.merge(o);
                        tx.commit();
                } catch (HibernateException e) {
                        handleException(e);
                }
        }

        public void update(T o) {
                try {
                        startOperation();
                //      session.clear();
                        session.update(o);
                        tx.commit();
                } catch (HibernateException e) {
                        handleException(e);
                }
        }

        public void delete(T o) {
                try {
                        startOperation();
                        session.delete(o);
                        tx.commit();
                } catch (HibernateException e) {
                        handleException(e);
                }
                ServiceLocator.closeSession();
        }

        @SuppressWarnings("unchecked")
        public List<T> readAll() {
                List<T> objects = null;
                try {
                        startOperation();
                        Query query = session.createQuery("from " + type.getName());
                        objects = query.list();
                        tx.commit();
                } catch (HibernateException e) {
                        handleException(e);
                }
                return objects;
        }

    public Query getQuery(String queryName) throws HibernateException  {
        session = ServiceLocator.getSession();
        return session.getNamedQuery(type.getSimpleName() + "." + queryName);
    }

        protected void handleException(HibernateException e)
                        throws DataAccessLayerException {
                ServiceLocator.rollback(tx);
                throw new DataAccessLayerException(e);
        }

        protected void startOperation() throws HibernateException {
                if (ServiceLocator.getFactory() == null)  {
                        ServiceLocator.buildFactory();
                }
                session = ServiceLocator.getSession();
                tx = session.beginTransaction();
        }
}


and here's the ServiceLocator class that uses the ThreadLocal to handle the session. one thing i'm not sure of is how / when to call session.close(); ... also i'm having a problem with cascading, but that's another thread.

Code:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class ServiceLocator {

        private static final ThreadLocal<Session> t = new ThreadLocal<Session>();
        private static SessionFactory factory;
    private static Log log = LogFactory.getLog(ServiceLocator.class);

        static  {
                try  {
                        factory = new Configuration().configure().buildSessionFactory();
                } catch (HibernateException e)  {
                        e.printStackTrace();
                }
        }

        public static Session getSession()  throws HibernateException  {
                Session s = t.get();
                if (s == null)  {
                        s = factory.openSession();
                        t.set(s);
                }
                return s;
        }

        public static void closeSession() {
                Session s = t.get();
                if (s != null)  {
                        try  {
                                s.close();
                        } catch (HibernateException e)  {
                                e.printStackTrace();
                        }
                }
                t.set(null);
        }

   public static void rollback(Transaction tx) {
        try {
            if (tx != null) {
                tx.rollback();
            }
        } catch (HibernateException ignored) {
            log.error("Couldn't rollback Transaction", ignored);
        }
    }

        public static SessionFactory getFactory() {
                return factory;
        }

        public static void buildFactory() {
                if (factory != null)  {
                        factory.close();
                }
                factory = new Configuration().configure().buildSessionFactory();
        }
}


any ideas? thanks, as soon as i get this figured out i'm gonna be cranking out the webapps in no time.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 21, 2006 7:13 am 
Expert
Expert

Joined: Thu Sep 22, 2005 10:29 am
Posts: 285
Location: Almassera/Valencia/Spain/EU/Earth/Solar system/Milky Way/Local Group/Virgo Supercluster
Have a look to CaveatEmptor

Particularly to HibernateUtil class.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 21, 2006 10:00 am 
Beginner
Beginner

Joined: Wed Jun 21, 2006 10:08 am
Posts: 26
As mentioned above, look at that.

I've had some limited success using HibernateSync. A eclipse plugin which auto-generates all the DAO code through the HBM files.

Also, Spring does have some nice features which will help you handle all the DAO stuff. Read through the Hibernate section of the Spring documentation for more info.

_________________
- Jonathan


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 21, 2006 11:08 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
http://hibernate.org/42.html
http://hibernate.org/43.html
http://hibernate.org/328.html


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 21, 2006 2:55 pm 
Beginner
Beginner

Joined: Sat Aug 19, 2006 8:04 pm
Posts: 30
thanks guys, i'm starting to understand all this stuff about sessions and units of work. however i'm still having some trouble here, at least this time it occurs all the time.

I'm using the HibernateUtil as is from caveat-empor (this is nice!) ... I'm also using the HibernateThreadFilter and HibernateListener from that project as well.

I've changed my DAO to look like this:
Code:
public class DAO<T, PK extends Serializable> implements GenericDAO<T, PK> {

   private Session session;
   private Class<T> type;
   
   public DAO() {
      session = HibernateUtil.getSessionFactory().getCurrentSession();
      this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
                           .getActualTypeArguments()[0];
   }
   
   @SuppressWarnings("unchecked")
   public PK create(T o) {
      Serializable pk = null;
      try {
         pk = session.save(o);
      } catch (HibernateException e) {
         handleException(e);
      }
      return (PK)pk;
   }

//similar crud methods omitted


this is better! now the problem i'm having is, the first hibernate session opens and gets closed. when i try to do a second database transaction, i get a session is closed exception.

Code:
avax.servlet.ServletException: Unhandled exception caught by the default exception handler.
   edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter.doFilter(HibernateThreadFilter.java:75)

root cause

net.sourceforge.stripes.exception.StripesServletException: Unhandled exception caught by the default exception handler.
   net.sourceforge.stripes.exception.DefaultExceptionHandler.handle(DefaultExceptionHandler.java:40)
   net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:218)
   edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter.doFilter(HibernateThreadFilter.java:48)

root cause

edu.upmc.ccweb.hibernate.DataAccessLayerException: org.hibernate.SessionException: Session is closed!
   edu.upmc.ccweb.hibernate.DAO.handleException(DAO.java:93)
   edu.upmc.ccweb.hibernate.DAO.getQuery(DAO.java:86)
   edu.upmc.ccweb.dosimetry.DAO.PatientDAO.getInactive(Unknown Source)
   edu.upmc.ccweb.dosimetry.manager.PatientManager.getInactive(Unknown Source)
   edu.upmc.ccweb.dosimetry.controller.ListInactivePatientsActionBean.listInactivePatients(Unknown Source)
   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   java.lang.reflect.Method.invoke(Method.java:585)
   net.sourceforge.stripes.controller.DispatcherServlet$6.intercept(DispatcherServlet.java:601)
   net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:145)
   net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:104)
   net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:142)
   net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:72)
   net.sourceforge.stripes.controller.DispatcherServlet.invokeEventHandler(DispatcherServlet.java:599)
   net.sourceforge.stripes.controller.DispatcherServlet.doPost(DispatcherServlet.java:155)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
   net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:215)
   edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter.doFilter(HibernateThreadFilter.java:48)


so what am i doing wrong?

here's my web.xml:

Code:
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">


    <filter>
        <filter-name>Hibernate Filter</filter-name>
        <filter-class>edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Hibernate Filter</filter-name>
        <dispatcher>REQUEST</dispatcher>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>


   <filter>
      <display-name>Stripes Filter</display-name>
      <filter-name>StripesFilter</filter-name>
      <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
      <init-param>
         <param-name>ActionResolver.UrlFilters</param-name>
         <param-value>/WEB-INF/classes</param-value>
      </init-param>
   </filter>
   
   <filter-mapping>
      <filter-name>StripesFilter</filter-name>
      <url-pattern>*.jsp</url-pattern>
      <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
   
   <filter-mapping>
       <filter-name>StripesFilter</filter-name>
       <servlet-name>Freemarker</servlet-name>
       <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
   
   <filter-mapping>
      <filter-name>StripesFilter</filter-name>
      <servlet-name>StripesDispatcher</servlet-name>
      <dispatcher>REQUEST</dispatcher>
   </filter-mapping>

   
   
   <servlet>
      <servlet-name>StripesDispatcher</servlet-name>
      <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
   
   <servlet-mapping>
      <servlet-name>StripesDispatcher</servlet-name>
      <url-pattern>*.action</url-pattern>
   </servlet-mapping>
   
   

   
   <servlet>
       <servlet-name>Freemarker</servlet-name>
       <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
   
       <init-param>
           <param-name>TemplatePath</param-name>
           <param-value>/</param-value>
       </init-param>
       <init-param>
           <param-name>template_update_delay</param-name>
           <param-value>0</param-value> <!-- 0 is for dev only! Use higher value otherwise. -->
       </init-param>
       <load-on-startup>1</load-on-startup>
   </servlet>
   
   <servlet-mapping>
       <servlet-name>Freemarker</servlet-name>
       <url-pattern>*.ftl</url-pattern>
   </servlet-mapping>
   

    <listener>
        <listener-class>edu.upmc.ccweb.hibernate.listener.HibernateListener</listener-class>
    </listener>
</web-app>


again, the first database access works great, any one after that and the session is closed. also i have

hibernate.current_session_context_class=thread

in my hibernate.properties

thanks again, actaully reading those articles was a big help. I now understand why managing this stuff really isn't part of hibernate's job (i wish it was though :P ).

the only thing i changed in the Filter, Listener and Util classes was the package name, I'm not sure why it's not working correctly (it's probably something simple i hope)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 21, 2006 2:56 pm 
Beginner
Beginner

Joined: Sat Aug 19, 2006 8:04 pm
Posts: 30
thanks guys, i'm starting to understand all this stuff about sessions and units of work. however i'm still having some trouble here, at least this time it occurs all the time.

I'm using the HibernateUtil as is from caveat-empor (this is nice!) ... I'm also using the HibernateThreadFilter and HibernateListener from that project as well.

I've changed my DAO to look like this:
Code:
public class DAO<T, PK extends Serializable> implements GenericDAO<T, PK> {

   private Session session;
   private Class<T> type;
   
   public DAO() {
      session = HibernateUtil.getSessionFactory().getCurrentSession();
      this.type = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass())
                           .getActualTypeArguments()[0];
   }
   
   @SuppressWarnings("unchecked")
   public PK create(T o) {
      Serializable pk = null;
      try {
         pk = session.save(o);
      } catch (HibernateException e) {
         handleException(e);
      }
      return (PK)pk;
   }

//similar crud methods omitted


this is better! now the problem i'm having is, the first hibernate session opens and gets closed. when i try to do a second database transaction, i get a session is closed exception.

Code:
avax.servlet.ServletException: Unhandled exception caught by the default exception handler.
   edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter.doFilter(HibernateThreadFilter.java:75)

root cause

net.sourceforge.stripes.exception.StripesServletException: Unhandled exception caught by the default exception handler.
   net.sourceforge.stripes.exception.DefaultExceptionHandler.handle(DefaultExceptionHandler.java:40)
   net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:218)
   edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter.doFilter(HibernateThreadFilter.java:48)

root cause

edu.upmc.ccweb.hibernate.DataAccessLayerException: org.hibernate.SessionException: Session is closed!
   edu.upmc.ccweb.hibernate.DAO.handleException(DAO.java:93)
   edu.upmc.ccweb.hibernate.DAO.getQuery(DAO.java:86)
   edu.upmc.ccweb.dosimetry.DAO.PatientDAO.getInactive(Unknown Source)
   edu.upmc.ccweb.dosimetry.manager.PatientManager.getInactive(Unknown Source)
   edu.upmc.ccweb.dosimetry.controller.ListInactivePatientsActionBean.listInactivePatients(Unknown Source)
   sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   java.lang.reflect.Method.invoke(Method.java:585)
   net.sourceforge.stripes.controller.DispatcherServlet$6.intercept(DispatcherServlet.java:601)
   net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:145)
   net.sourceforge.stripes.controller.BeforeAfterMethodInterceptor.intercept(BeforeAfterMethodInterceptor.java:104)
   net.sourceforge.stripes.controller.ExecutionContext.proceed(ExecutionContext.java:142)
   net.sourceforge.stripes.controller.ExecutionContext.wrap(ExecutionContext.java:72)
   net.sourceforge.stripes.controller.DispatcherServlet.invokeEventHandler(DispatcherServlet.java:599)
   net.sourceforge.stripes.controller.DispatcherServlet.doPost(DispatcherServlet.java:155)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
   javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
   net.sourceforge.stripes.controller.StripesFilter.doFilter(StripesFilter.java:215)
   edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter.doFilter(HibernateThreadFilter.java:48)


so what am i doing wrong?

here's my web.xml:

Code:
<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">


    <filter>
        <filter-name>Hibernate Filter</filter-name>
        <filter-class>edu.upmc.ccweb.hibernate.filter.HibernateThreadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Hibernate Filter</filter-name>
        <dispatcher>REQUEST</dispatcher>
        <url-pattern>*.action</url-pattern>
    </filter-mapping>


   <filter>
      <display-name>Stripes Filter</display-name>
      <filter-name>StripesFilter</filter-name>
      <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
      <init-param>
         <param-name>ActionResolver.UrlFilters</param-name>
         <param-value>/WEB-INF/classes</param-value>
      </init-param>
   </filter>
   
   <filter-mapping>
      <filter-name>StripesFilter</filter-name>
      <url-pattern>*.jsp</url-pattern>
      <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
   
   <filter-mapping>
       <filter-name>StripesFilter</filter-name>
       <servlet-name>Freemarker</servlet-name>
       <dispatcher>REQUEST</dispatcher>
   </filter-mapping>
   
   <filter-mapping>
      <filter-name>StripesFilter</filter-name>
      <servlet-name>StripesDispatcher</servlet-name>
      <dispatcher>REQUEST</dispatcher>
   </filter-mapping>

   
   
   <servlet>
      <servlet-name>StripesDispatcher</servlet-name>
      <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
   
   <servlet-mapping>
      <servlet-name>StripesDispatcher</servlet-name>
      <url-pattern>*.action</url-pattern>
   </servlet-mapping>
   
   

   
   <servlet>
       <servlet-name>Freemarker</servlet-name>
       <servlet-class>freemarker.ext.servlet.FreemarkerServlet</servlet-class>
   
       <init-param>
           <param-name>TemplatePath</param-name>
           <param-value>/</param-value>
       </init-param>
       <init-param>
           <param-name>template_update_delay</param-name>
           <param-value>0</param-value> <!-- 0 is for dev only! Use higher value otherwise. -->
       </init-param>
       <load-on-startup>1</load-on-startup>
   </servlet>
   
   <servlet-mapping>
       <servlet-name>Freemarker</servlet-name>
       <url-pattern>*.ftl</url-pattern>
   </servlet-mapping>
   

    <listener>
        <listener-class>edu.upmc.ccweb.hibernate.listener.HibernateListener</listener-class>
    </listener>
</web-app>


again, the first database access works great, any one after that and the session is closed. also i have

hibernate.current_session_context_class=thread

in my hibernate.properties

thanks again, actaully reading those articles was a big help. I now understand why managing this stuff really isn't part of hibernate's job (i wish it was though :P ).

the only thing i changed in the Filter, Listener and Util classes was the package name, I'm not sure why it's not working correctly (it's probably something simple i hope)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.