-->
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.  [ 3 posts ] 
Author Message
 Post subject: Korrekte Pattern?
PostPosted: Sat Dec 22, 2007 2:32 pm 
Newbie

Joined: Sat Dec 22, 2007 2:26 pm
Posts: 3
Hallo!
Ich bin noch recht neu in Sachen Hibernate und bin sehr stark angetan von der ganzen Sache..
Ich entwickle im Umfeld Webapplikationen, hauptsächlich auf Tomcat.
Um mein Session Handling umzusetzen, habe ich mir einen Filter geschrieben.
Kann einer mal bitte drüberschauen ob ich mir das Leben zu einfach gemacht habe oder was übersehen habe?

Hier mein Filter:

Code:

public class HibernateSessionFilter implements Filter {

    private SessionFactory sf;

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        try {
           HibernateUtil.logger.info("HIBERNATE FILTER: Getting Session and opening transaction..");
            sf.getCurrentSession().beginTransaction();
            HibernateUtil.logger.info("HIBERNATE FILTER: Session open, transaction ready");
           
            //Anfrage weiterschicken..
            chain.doFilter(request, response);
           
            // Anfrage kommt zurück
            HibernateUtil.logger.info("HIBERNATE FILTER: Committing transaction and closing session..");
            sf.getCurrentSession().getTransaction().commit();
            sf.getCurrentSession().close();
            HibernateUtil.logger.info("HIBERNATE FILTER: Transaction and session closed");

        } catch (Throwable ex) {
           HibernateUtil.logger.info(ex.toString());
            try {
                if (sf.getCurrentSession().getTransaction().isActive()) {
                    sf.getCurrentSession().getTransaction().rollback();
                }
            } catch (Throwable rbEx) {
               HibernateUtil.logger.info(rbEx.toString());
            }
        }
    }

    public void init(FilterConfig filterConfig) throws ServletException {
        HibernateUtil.logger.info("HIBERNATE FILTER: Filter initializing..");
        HibernateUtil.logger.info("HIBERNATE FILTER: Aquiring SessionFactory from HibernateUtil..");
        try {
           sf = HibernateUtil.getSessionFactory();
           HibernateUtil.logger.info("HIBERNATE FILTER: Filter ready.");
        }
        catch (Exception e) {
           HibernateUtil.logger.fatal(e.toString());
        }
    }

    public void destroy() {
       HibernateUtil.logger.info("HIBERNATE FILTER: Filter unloaded.");
    }
}


und hier meine hibernate.cf.xml:

Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
    </property>
    <property name="hibernate.connection.url">
       jdbc:mysql://217.***.***.***/**
    </property>
    <property name="hibernate.connection.username">****</property>
    <property name="hibernate.connection.password">****</property>
   
      <property name="c3p0.min_size">10</property>
   <property name="c3p0.max_size">100</property>
   <property name="c3p0.timeout">10</property>
   <property name="c3p0.acquireRetryAttempts">30</property>
   <property name="c3p0.acquireIncrement">5</property>
   <property name="c3p0.idleConnectionTestPeriod">300</property>
   <property name="c3p0.initialPoolSize">20</property>
   <property name="c3p0.maxPoolSize">100</property>
   <property name="c3p0.maxIdleTime">300</property>
   <property name="c3p0.maxStatements">50</property>
   <property name="c3p0.minPoolSize">10</property>
   
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="show_sql">false</property>
    <property name="transaction.factory_class">
      org.hibernate.transaction.JDBCTransactionFactory
    </property>
    <property name="hibernate.cache.provider_class">
      org.hibernate.cache.HashtableCacheProvider
    </property>
    <property name="hibernate.hbm2ddl.auto">update</property>
    <property name="hibernate.current_session_context_class">org.hibernate.context.ThreadLocalSessionContext</property>
    <mapping resource="Area.hbm.xml"/>
    <mapping resource="Site.hbm.xml"/>
    <mapping resource="Company.hbm.xml"/>
    <mapping resource="Employee.hbm.xml"/>
    <mapping resource="Currency.hbm.xml"/>
    <mapping resource="Customer.hbm.xml"/>
    <mapping resource="Product.hbm.xml"/>
    <mapping resource="Forecast.hbm.xml"/>
    <mapping resource="ForecastValue.hbm.xml"/>
  </session-factory>

</hibernate-configuration>



Passt das so?
Muss ich bei Webapplikationen noch spezielles beachten damit sich die Sessions nicht ins Gehege kommen?

Vielen Dank für Eure Hilfe & schöne Feiertage!

Michael


Top
 Profile  
 
 Post subject: Korrekte Pattern?
PostPosted: Wed Jan 02, 2008 10:02 am 
Newbie

Joined: Wed Jan 02, 2008 9:04 am
Posts: 1
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


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jan 08, 2008 1:58 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
Punkt 2 von scheer4711 ist nicht ganz korrekt.
Du hast einen Current_session_context definiert und zwar auf thread bzw. ThreadLocalCurrentSessionContext.

Das bedeutet, dass ein commit/rollback auch die Session zu macht.

Vorteil dieser current_session_context ist, dass Du nirgendwo eine neue Session öffnen musst, sondern einfach sessionFactory.getCurrentSession verwenden kannst.

Du solltest dem Benutzer aber zumindestens eine Fehlermeldung anzeigen, wenn eine Exception passiert.

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


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