| <!DOCTYPE html> |
| |
| |
| <!-- |
| | Generated by Apache Maven Doxia Site Renderer 2.0.0 from src/site/xdoc/howto/hibernate-howto.xml at 10 Sep 2025 |
| | Rendered using Apache Maven Fluido Skin 2.1.0 |
| --> |
| <html xmlns="http://www.w3.org/1999/xhtml" lang="en"> |
| <head> |
| <meta charset="UTF-8" /> |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| <meta name="generator" content="Apache Maven Doxia Site Renderer 2.0.0" /> |
| <title>Hibernate Howto – Apache Turbine</title> |
| <link rel="stylesheet" href="../css/apache-maven-fluido-2.1.0.min.css" /> |
| <link rel="stylesheet" href="../css/site.css" /> |
| <link rel="stylesheet" href="../css/print.css" media="print" /> |
| <script src="../js/apache-maven-fluido-2.1.0.min.js"></script> |
| <link rel="icon" type="image/png" sizes="48x48" href="https://apache.org/favicons/favicon.ico"> |
| <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
| <style>.github-fork-ribbon:before { background-color: orange; }</style> |
| </head> |
| <body> |
| <a class="github-fork-ribbon right-top" href="https://github.com/apache/turbine-build" data-ribbon="Fork me on GitHub">Fork me on GitHub</a> |
| <div class="container-fluid container-fluid-top"> |
| <header> |
| <div id="banner"> |
| <div class="pull-left"><div id="bannerLeft"><h1><a href="https://turbine.apache.org/"><img src="https://www.apache.org/img/feather_glyph_notm.png" style="width: 50px;" /> The Apache Turbine project</a></h1></div></div> |
| <div class="pull-right"><div id="bannerRight"><h1><a href="https://turbine.apache.org/"><img src="https://turbine.apache.org/images/logo.gif" alt="Apache Turbine" /></a></h1></div></div> |
| <div class="clear"><hr/></div> |
| </div> |
| |
| <div id="breadcrumbs"> |
| <ul class="breadcrumb"> |
| <li id="publishDate">Last Published: 01 Apr 2025<span class="divider">|</span> |
| </li> |
| <li id="projectVersion">Version: 7.1-SNAPSHOT</li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://turbine.apache.org/fulcrum/">Fulcrum</a></li> |
| <li class="pull-right"><span class="divider">|</span> |
| <a href="https://turbine.apache.org/">Turbine</a></li> |
| <li class="pull-right"><a href="https://www.apache.org">Apache</a></li> |
| </ul> |
| </div> |
| </header> |
| <div class="row-fluid"> |
| <header id="leftColumn" class="span2"> |
| <nav class="well sidebar-nav"> |
| <ul class="nav nav-list"> |
| <li class="nav-header">General Information</li> |
| <li><a href="../index.html">Overview</a></li> |
| <li><a href="../features.html">Features</a></li> |
| <li><a href="../fsd.html">Specification</a></li> |
| <li><a href="../getting-started.html">Getting Started</a></li> |
| <li><a href="../how-to-build.html">Howto Build Turbine</a></li> |
| <li><a href="../changes-report.html">Changes</a></li> |
| <li class="nav-header">Documentation</li> |
| <li><a href="../services/index.html"><span class="icon-chevron-right"></span>Services</a></li> |
| <li><a href="../howto/index.html"><span class="icon-chevron-down"></span>Howtos</a> |
| <ul class="nav nav-list"> |
| <li><a href="../howto/action-event-howto.html">Action Events Howto</a></li> |
| <li><a href="../howto/annotations.html">Annotations Howto</a></li> |
| <li><a href="../howto/configuration-howto.html">Configuration Howto</a></li> |
| <li><a href="../howto/extend-user-howto.html">Extend User Howto</a></li> |
| <li class="active"><a>Hibernate OM Howto</a></li> |
| <li><a href="../howto/intake-howto.html">Intake Howto</a></li> |
| <li><a href="../howto/jsp-howto.html">JSP Howto</a></li> |
| <li><a href="../howto/migrate-from-2_1-howto.html">Migrating from 2.1 to 2.2</a></li> |
| <li><a href="../howto/migrate-from-2_2-howto.html">Migrating from 2.2 to 2.3</a></li> |
| <li><a href="../howto/migrate-from-2_3-howto.html">Migrating from 2.3 to 4.0</a></li> |
| <li><a href="../howto/migrate-from-4_0-howto.html">Migrating from 4.0 to 5.0</a></li> |
| <li><a href="../howto/pullmodel-howto.html">Pull Model Howto</a></li> |
| <li><a href="../howto/python-howto.html">Python Howto</a></li> |
| <li><a href="../howto/security-howto.html">Security Howto</a></li> |
| <li><a href="../howto/services-howto.html">Services Howto</a></li> |
| <li><a href="../howto/url-mapper-howto.html">URL Mapper Howto</a></li> |
| <li><a href="../howto/url-rewriting-howto.html">URL Rewriting Howto</a></li> |
| <li><a href="../howto/context-howto.html">Velocity Context Howto</a></li> |
| <li><a href="../howto/velocity-site-howto.html">Velocity Site Howto</a></li> |
| <li><a href="../howto/velocityonlylayout-howto.html">VelocityOnlyLayout Howto</a></li> |
| </ul></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/TURBINE">Wiki</a></li> |
| <li><a href="../apidocs/index.html">JavaDocs</a></li> |
| <li class="nav-header">Development</li> |
| <li><a href="../proposals.html">Proposals</a></li> |
| <li><a href="../how-to-help.html">How To Help</a></li> |
| <li><a href="../todo.html">Todo</a></li> |
| <li class="nav-header">Project Documentation</li> |
| <li><a href="../project-info.html"><span class="icon-chevron-right"></span>Project Information</a></li> |
| <li><a href="../project-reports.html"><span class="icon-chevron-right"></span>Project Reports</a></li> |
| <li class="nav-header">Apache</li> |
| <li><a href="https://www.apache.org/">Apache Website</a></li> |
| <li><a href="https://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/how-it-works.html">How the ASF works</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li><a href="https://www.apache.org/security/">Security</a></li> |
| </ul> |
| </nav> |
| <div class="well sidebar-nav"> |
| <form id="search-form" action="https://www.google.com/search" method="get" > |
| <input value="http://turbine.apache.org/turbine/turbine-7-0" name="sitesearch" type="hidden" /> |
| <input class="search-query" name="q" id="query" type="text" placeholder="Search with Google..." /> |
| </form> |
| <div id="poweredBy"> |
| <div class="clear"></div> |
| <div class="clear"></div> |
| <a href="https://maven.apache.org/" class="builtBy" target="_blank"><img class="builtBy" alt="Built by Maven" src="../images/logos/maven-feather.png" /></a> |
| </div> |
| </div> |
| </header> |
| <main id="bodyColumn" class="span10"> |
| |
| |
| |
| |
| <section><a id="Introduction"></a> |
| <h1>Introduction</h1> |
| |
| <p> |
| This is a HOWTO on implementing Hibernate as the database OM layer. The motivating factors for using Hibernate |
| are: |
| </p> |
| <ol style="list-style-type: decimal;"> |
| |
| <li> |
| You just use POJO (Plain Old Java Objects) versus generated objects. |
| </li> |
| |
| <li> |
| You can either start with Java objects and create your database schema from there, or |
| start with a database schema, and map the Java objects to the schema. |
| </li> |
| |
| <li> |
| Extensive performance optimizations built into the Hibernate engine. |
| </li> |
| |
| <li> |
| Leverage Avalon component use in Turbine 2.3! |
| </li> |
| </ol> |
| |
| |
| <p> |
| Please review the content available from the Hibernate homepage. This howto assumes |
| you already are confortable with the various Hibernate concepts. |
| </p> |
| |
| <p> |
| In this example, we will take a simple schema with a single table and integrate Hibernate into |
| a Turbine action. We will talk about best practices for Hibernate and Turbine. |
| </p> |
| <ol style="list-style-type: decimal;"> |
| |
| <li> |
| Configure project dependencies. |
| </li> |
| |
| <li> |
| Directory Structures |
| </li> |
| |
| |
| <li> |
| Setup Avalon component configuration. |
| </li> |
| |
| |
| <li> |
| Setup Hibernate mapping files. |
| </li> |
| |
| <li> |
| Create static ServiceLocator class. |
| </li> |
| |
| <li> |
| Create filter that manages the Hibernate Session. |
| </li> |
| |
| <li> |
| Setup PersitenceException handling |
| </li> |
| </ol> |
| |
| |
| </section> |
| |
| <section><a id="Directory_Structures"></a> |
| <h1>Directory Structures</h1> |
| |
| <p> |
| While you can organize your directory structure however you like, I tend to have structure like: |
| </p> |
| |
| <pre class="prettyprint"><code> |
| /src/java/com/my/project/bizobj business objects reside |
| /src/java/com/my/project/om POJO objects mapped to database reside |
| /src/java/com/my/project/om/persist manager objects that faciliate retrieve POJO objects |
| /src/java/com/my/project/om/filter Servlet Filter lives that maintains the Hibernate Session |
| /src/java/ where hibernate.hbm.xml and hibernate.cfg.xml files live |
| |
| </code></pre> |
| |
| </section> |
| |
| <section><a id="Configure_project_dependencies"></a> |
| <h1>Configure project dependencies</h1> |
| |
| <p> |
| The easiest way to maintain a project is to use Maven. Here are the sample |
| dependencies for your project.xml. |
| </p> |
| |
| <pre class="prettyprint"><code> |
| |
| <dependency> |
| <id>hibernate</id> |
| <version>2.0-beta6</version> |
| <properties> |
| <war.bundle.jar>true</war.bundle.jar> |
| </properties> |
| </dependency> |
| <dependency> |
| <id>hibernate:hibernate-avalon</id> |
| <version>0.1</version> |
| <properties> |
| <war.bundle.jar>true</war.bundle.jar> |
| </properties> |
| </dependency> |
| <dependency> |
| <id>dom4j</id> |
| <version>1.4</version> |
| <properties> |
| <war.bundle.jar>true</war.bundle.jar> |
| </properties> |
| </dependency> |
| <dependency> |
| <id>cglib</id> |
| <version>rc2-1.0</version> |
| <properties> |
| <war.bundle.jar>true</war.bundle.jar> |
| </properties> |
| </dependency> |
| <dependency> |
| <id>jcs</id> |
| <version>1.0-dev</version> |
| <properties> |
| <war.bundle.jar>true</war.bundle.jar> |
| </properties> |
| </dependency> |
| |
| </code></pre> |
| |
| <p> |
| The key jar file is the hibernate-avalon.jar file, it contains the Avalon wrapper |
| for Hibernate, and can be used with any Avalon container. |
| </p> |
| |
| </section> |
| |
| <section><a id="Setting_up_Avalon_Configuration"></a> |
| <h1>Setting up Avalon Configuration</h1> |
| |
| |
| <p> |
| We leverage the Avalon based HibernateService that is hosted as part of the |
| HibernateExt project. You must specify the name of the service, as well as the implementing |
| service in your componentConfiguration.xml file. Other configuration parameters can be passed |
| in as well. |
| </p> |
| |
| <pre class="prettyprint"><code> |
| |
| |
| <my-system> |
| <component |
| role="net.sf.hibernate.avalon.HibernateService" |
| class="net.sf.hibernate.avalon.HibernateServiceImpl"> |
| </component> |
| </my-system> |
| |
| |
| </code></pre> |
| |
| |
| <p> |
| The componentRoles file also defines how to access the component. Here is a |
| very simple componentRoles.xml file: |
| </p> |
| |
| <pre class="prettyprint"><code> |
| |
| |
| <role-list> |
| <role |
| name="net.sf.hibernate.avalon.HibernateService" |
| shorthand="hibernate" |
| default-class="net.sf.hibernate.avalon.HibernateServiceImpl"/> |
| </role-list> |
| |
| |
| </code></pre> |
| </section> |
| |
| |
| |
| <section><a id="Setup_Hibernate_mapping_files"></a> |
| <h1>Setup Hibernate mapping files</h1> |
| |
| <p> |
| This section will not go into depth on how to configure the hibernate.cfg.xml and |
| hibernate.hbm.xml files. However, if you don't specify in the componentConfiguration.xml |
| file where they are located, then they should be placed in your src/java/ directory. |
| </p> |
| |
| <p> |
| The exact configuration is dependent on the environment Turbine is running in, however |
| I highly recommend that you use the JNDI look up of the datasource, and use DBCP for your |
| connection pooling. I have found that when using Hibernate in cactus tests, you may need to |
| increase the pool size required in order to not run out of connections, however this doesn't |
| seem to apply to running as a web application. |
| </p> |
| </section> |
| |
| |
| |
| <section><a id="Create_static_ServiceLocator_class."></a> |
| <h1>Create static ServiceLocator class.</h1> |
| |
| <p> |
| Currently this class is not integrated into Turbine, so you will need to provide an implemation yourself. |
| This provides a static method of retrieving your Hibernate Session. |
| </p> |
| |
| |
| <pre class="prettyprint"><code> |
| |
| package com.upstate.cellculture.om.persist; |
| |
| import net.sf.hibernate.HibernateException; |
| import net.sf.hibernate.JDBCException; |
| import net.sf.hibernate.Session; |
| import net.sf.hibernate.SessionFactory; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| /** |
| * This class is used to get Hibernate Sessions and may |
| * also contain methods (in the future) to get DBConnections |
| * or Transactions from JNDI. |
| */ |
| public class ServiceLocator |
| { |
| //~ Static fields/initializers ============================================= |
| public final static String SESSION_FACTORY = "hibernate/sessionFactory"; |
| public static final ThreadLocal session = new ThreadLocal(); |
| private static SessionFactory sf = null; |
| private static ServiceLocator me; |
| private static Log log = LogFactory.getLog(ServiceLocator.class); |
| |
| static { |
| try |
| { |
| me = new ServiceLocator(); |
| } |
| catch (Exception e) |
| { |
| log.fatal("Error occurred initializing ServiceLocator"); |
| e.printStackTrace(); |
| } |
| } |
| |
| //~ Constructors =========================================================== |
| |
| private ServiceLocator() throws HibernateException, JDBCException |
| {} |
| |
| //~ Methods ================================================================ |
| |
| public static Session currentSession() throws PersistenceException |
| { |
| Session s = (Session) session.get(); |
| |
| if (s == null) |
| { |
| s = PersistenceManager.openSession(); |
| if (log.isDebugEnabled()) |
| { |
| log.debug("Opened hibernate session."); |
| } |
| |
| session.set(s); |
| } |
| |
| return s; |
| } |
| |
| public static void closeSession() throws HibernateException, JDBCException |
| { |
| Session s = (Session) session.get(); |
| session.set(null); |
| |
| if (s != null) |
| { |
| if (s.isOpen()) |
| { |
| s.flush(); |
| s.close(); |
| |
| if (log.isDebugEnabled()) |
| { |
| log.debug("Closed hibernate session."); |
| } |
| } |
| } |
| else |
| { |
| log.warn("Hibernate session was inadvertently already closed."); |
| |
| } |
| } |
| } |
| |
| </code></pre> |
| </section> |
| |
| <section><a id="Create_Servlet_Filter."></a> |
| <h1>Create Servlet Filter.</h1> |
| |
| <p> |
| The servlet Filter is required if you use lazy loading of objects because you need to open a Hibernate sesion, and keeps it open through the view layer. |
| This ensures that each user get's their own Hibernate Session. ?? Should this be done |
| through some sort of SessionValidator? |
| |
| </p> |
| |
| |
| <pre class="prettyprint"><code> |
| |
| package com.upstate.cellculture.filter; |
| |
| import java.io.IOException; |
| |
| import javax.servlet.Filter; |
| import javax.servlet.FilterChain; |
| import javax.servlet.FilterConfig; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| import javax.servlet.http.HttpSession; |
| |
| import net.sf.hibernate.Session; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| |
| import com.upstate.cellculture.om.persist.PersistenceException; |
| import com.upstate.cellculture.om.persist.ServiceLocator; |
| |
| public class ActionFilter implements Filter |
| { |
| //~ Static fields/initializers ============================================= |
| |
| //~ Instance fields ======================================================== |
| |
| /** |
| * The <code>Log</code> instance for this class |
| */ |
| private Log log = LogFactory.getLog(ActionFilter.class); |
| private FilterConfig filterConfig = null; |
| |
| //~ Methods ================================================================ |
| |
| public void init(FilterConfig filterConfig) throws ServletException |
| { |
| this.filterConfig = filterConfig; |
| |
| } |
| |
| /** |
| * Destroys the filter. |
| */ |
| public void destroy() |
| { |
| filterConfig = null; |
| } |
| |
| public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException |
| { |
| // cast to the types I want to use |
| HttpServletRequest request = (HttpServletRequest) req; |
| HttpServletResponse response = (HttpServletResponse) resp; |
| HttpSession session = request.getSession(true); |
| |
| Session ses = null; |
| boolean sessionCreated = false; |
| |
| try |
| { |
| chain.doFilter(request, response); |
| } |
| finally |
| { |
| try |
| { |
| ServiceLocator.closeSession(); |
| } |
| catch (Exception exc) |
| { |
| log.error("Error closing hibernate session.", exc); |
| exc.printStackTrace(); |
| } |
| } |
| } |
| |
| public static Session getSession() throws PersistenceException |
| { |
| try |
| { |
| |
| return ServiceLocator.currentSession(); |
| } |
| catch (Exception e) |
| { |
| throw new PersistenceException("Could not find current Hibernate session.", e); |
| } |
| |
| } |
| } |
| |
| |
| </code></pre> |
| </section> |
| |
| |
| |
| |
| |
| |
| <section><a id="Implementing_Manager_classes"></a> |
| <h1>Implementing Manager classes</h1> |
| |
| <p> |
| To centralize access to the database, we create Manager classes. Often Manager |
| classes are called DAO (Data Access Classes). Here is an example: |
| </p> |
| |
| <pre class="prettyprint"><code> |
| |
| /* |
| * Created on Apr 28, 2003 |
| * |
| */ |
| package com.upstate.cellculture.om.persist; |
| import java.util.List; |
| |
| import net.sf.hibernate.Query; |
| import net.sf.hibernate.Session; |
| |
| import com.upstate.cellculture.om.Technician; |
| /** |
| * @author tmckinney |
| * |
| * Centralizes all access to the Technicians table |
| */ |
| public class TechnicianManager |
| { |
| private static List allTechnicians; |
| public static void save(Technician technician) throws PersistenceException |
| { |
| try |
| { |
| |
| ServiceLocator.currentSession().save(technician); |
| |
| } |
| catch (Exception e) |
| { |
| throw new PersistenceException("Could not save.", e); |
| } |
| } |
| |
| public static Technician retrieveByPK(long technicianId) throws PersistenceException |
| { |
| try |
| { |
| Technician technician= (Technician) ServiceLocator.currentSession().load(Technician.class, new Long(technicianId)); |
| return technician; |
| } |
| catch (Exception e) |
| { |
| throw new PersistenceException("Could not retrieve.", e); |
| } |
| } |
| |
| |
| public static List retrieveAllTechnicians() throws PersistenceException |
| { |
| if (allTechnicians == null) |
| { |
| try |
| { |
| Query q = ServiceLocator.currentSession().createQuery("from technician in class " + Technician.class +" order by upper(technician.name)"); |
| allTechnicians = q.list(); |
| session.flush(); |
| } |
| catch (Exception e) |
| { |
| e.printStackTrace(); |
| throw new PersistenceException(e); |
| } |
| } |
| return allTechnicians; |
| |
| } |
| |
| |
| } |
| |
| |
| </code></pre> |
| |
| <p> |
| By using this TechnicianManager class, we could feasibly swap out the Hibernate code |
| for another OM strategy. Even better would be to have a TechnicianManager interface |
| and a TechicianManagerImpl class. Possibly loaded via Avalon as a component! |
| </p> |
| </section> |
| |
| <section><a id="Setup_PersitenceException_handling"></a> |
| <h1>Setup PersitenceException handling</h1> |
| |
| <p> |
| By catching a generice Persistence Exception that wraps all the |
| thrown exceptions we can just catch a single exception and then |
| retrieve what type of exception it is. |
| </p> |
| |
| <pre class="prettyprint"><code> |
| |
| package com.upstate.cellculture.om.persist; |
| |
| import org.apache.commons.lang.exception.NestableException; |
| /** |
| * A general PersistenceException that is thrown by all Manager classes. |
| * |
| */ |
| public class PersistenceException extends NestableException |
| { |
| //~ Constructors =========================================================== |
| |
| /** |
| * Constructor for PersistenceException. |
| */ |
| public PersistenceException() |
| { |
| super(); |
| } |
| |
| /** |
| * Constructor for PersistenceException. |
| * |
| * @param message |
| */ |
| public PersistenceException(String message) |
| { |
| super(message); |
| } |
| |
| /** |
| * Constructor for PersistenceException. |
| * |
| * @param message |
| * @param cause |
| */ |
| public PersistenceException(String message, Throwable cause) |
| { |
| super(message, cause); |
| } |
| |
| /** |
| * Constructor for PersistenceException. |
| * |
| * @param cause |
| */ |
| public PersistenceException(Throwable cause) |
| { |
| super(cause); |
| } |
| |
| } |
| |
| |
| </code></pre> |
| |
| </section> |
| |
| </main> |
| </div> |
| </div> |
| <hr/> |
| <footer> |
| <div class="container-fluid"> |
| <div class="row-fluid"> |
| <p>© 2000–2025 |
| <a href="https://www.apache.org/">The Apache Software Foundation</a> |
| </p> |
| </div> |
| </div> |
| </footer> |
| </body> |
| </html> |