Feb 21 2008

Hibernate with Guice – Part II

Published by at 8:21 PM under Guice,Hibernate,Java,NetBeans



Welcome back to Part II about using Hibernate with Guice. If you just stepped in, i recommend first to read Part I here.


Part II – Adding Guice to the Hibernate-Application

This application uses Guice’s Dependency Injection to create the HibernateConnection-instance and the OrdersDAO-instance. You can see that HibernateUtil don’t need STATICs anymore. Access to HibernateUtil is wrapped through a HibernateConnection which is created in a ConnectionProvider as a Singleton. Providers are acting as Factories in creating and returning Objects.

Ready for action?

Create a new Project “HibernateConnectionWithGuice“, add the Hibernate, MySql and Guice JARs to it and create the following files:



OrdersController.java

package eu.jdevelop.hibernateconnectionwithguice.controller;

import com.google.inject.Inject;
import eu.jdevelop.hibernateconnectionwithguice.dao.impl.OrdersDAO;

/**
 * This class is used to retrieve the one and only instance of
 * OrdersDAO (it is a Singleton). We are using Guice to inject a
 * OrdersDAO-instance into our controller.
 *
 * @author Siegfried Bolz
 */
public class OrdersController {

    private OrdersDAO dao;

     @Inject
    public void setOrdersDAO(OrdersDAO dao) {
        this.dao = dao;
    }

    public OrdersDAO getOrdersDAO() {
        return dao;
    }

} // .EOF



HibernateConnection.java

package eu.jdevelop.hibernateconnectionwithguice.dao.impl;

import eu.jdevelop.hibernateconnectionwithguice.dao.IConnection;
import eu.jdevelop.hibernateconnectionwithguice.util.HibernateUtil;
import org.hibernate.Session;

/**
 * Wrapper-class for OrdersDAO (and all other DAO's).
 * If you want to use an other HibernateUtil, just change the
 * ConnectionProvider.class -Binding in GuiceModule or create
 * other Provider- and Connection classes.
 *
 * @author Siegfried Bolz
 */
public class HibernateConnection implements IConnection<session>{

    private HibernateUtil hibernateUtil;

    public HibernateConnection(HibernateUtil hibernateUtil) {
        this.hibernateUtil = hibernateUtil;
    }

    public void connect() {
       hibernateUtil.Configure(true);
       hibernateUtil.beginTransaction();
    }

    public void disConnect() {
        hibernateUtil.closeSessionFactory();
    }

    public Session getSession() {
        return hibernateUtil.getSession();
    }

    public void rollbackTransaction() {
        hibernateUtil.rollbackTransaction();
    }

    public void commitTransaction() {
        hibernateUtil.commitTransaction();
    }

    public void closeSession() {
        hibernateUtil.closeSession();
    }

} // .EOF



OrdersDAO.java

package eu.jdevelop.hibernateconnectionwithguice.dao.impl;

import com.google.inject.Singleton;
import eu.jdevelop.hibernateconnectionwithguice.dao.IConnection;
import eu.jdevelop.hibernateconnectionwithguice.dao.IGenericDAO;
import eu.jdevelop.hibernateconnectionwithguice.exceptions.InfrastructureException;
import eu.jdevelop.hibernateconnectionwithguice.model.*;
import java.util.Collection;
import org.hibernate.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * DAO for Table "orders". Running as a Singleton.
 *
 * @author Siegfried Bolz
 */
@Singleton
public class OrdersDAO implements IGenericDAO<orders> {


    private int counter=0; // remove if not needed.

    private Log logger = LogFactory.getLog(OrdersDAO.class);
    private HibernateConnection connection;


    public void makePersistent(Orders orders) throws InfrastructureException {

        /**
         * You can see here if "ordersController2" has successfully used
         * the OrdersDAO-Singleton or created a new OrdersDAO-instance.
         * Remove if not needed.
         */
        logger.info("****** Access to OrderDAO: " + ++counter);

        try {
            Session session = (Session) this.getConnection().getSession();
            session.save(orders);

        } catch (HibernateException ex) {
            this.getConnection().rollbackTransaction();
            logger.error("Exception in OrdersDAO.makePersistent().", ex);
            throw new InfrastructureException(ex);
        }

    }

    public void makePersistentUpdate(Orders orders) throws InfrastructureException {
        try {
            Session session = (Session) this.getConnection().getSession();
            session.update(orders);

        } catch (HibernateException ex) {
            this.getConnection().rollbackTransaction();
            logger.error("Exception in OrdersDAO.makePersistentUpdate().", ex);
            throw new InfrastructureException(ex);
        }

    }

    public void makeTransient(Orders orders) throws InfrastructureException {
        try {
            Session session = (Session) this.getConnection().getSession();
            session.delete(orders);

        } catch (HibernateException ex) {
            this.getConnection().rollbackTransaction();
            logger.error("Exception in OrdersDAO.makeTransient(). Rollback activated.", ex);
            throw new InfrastructureException(ex);
        }
    }

    /**
     * Search for all Orders-Entities in Database.
     *
     * @return Collection
     * @throws eu.jdevelop.hibernateconnectionwithguice.exceptions.InfrastructureException
     */
    public Collection findAll() throws InfrastructureException {
        Collection collections;
        try {

            Session session = (Session) this.getConnection().getSession();
            collections = session.createCriteria(Orders.class).list();

            this.getConnection().commitTransaction();
        } catch (HibernateException ex) {
            logger.error("Exception in OrdersDAO.findAll().", ex);
            throw new InfrastructureException(ex);
        } finally {
            this.getConnection().closeSession();
        }

        return collections;
    }

    /**
     * Set HibernateConnection (Wrapper for HibernateUtil)
     *
     * @param connection
     * @throws eu.jdevelop.hibernateconnectionwithguice.exceptions.InfrastructureException
     */
    public void setConnection(IConnection connection) throws InfrastructureException {
        this.connection = (HibernateConnection) connection;
    }

    /**
     * Use this method to gain access to the Hibernate-Wrapper.
     *
     * @return
     * @throws eu.jdevelop.hibernateconnectionwithguice.exceptions.InfrastructureException
     */
    public IConnection getConnection() throws InfrastructureException {
        return this.connection;
    }

} // .EOF



IConnection.java

package eu.jdevelop.hibernateconnectionwithguice.dao;

/**
 * Interface for creating Database-Connection-Wrappers.
 *
 * @author Siegfried Bolz
 */
public interface IConnection<t> {

    public void connect();

    public void disConnect();

    public T getSession();

    public void rollbackTransaction();

    public void commitTransaction();

    public void closeSession();

} // .EOF



IGenericDAO.java

package eu.jdevelop.hibernateconnectionwithguice.dao;

import eu.jdevelop.hibernateconnectionwithguice.exceptions.InfrastructureException;

/**
 * Interface of the Generic DAO. Use this to create DAO-Implementations
 * for the models.
 *
 * @author Siegfried Bolz
 */
public interface IGenericDAO<t> {

    public void setConnection(IConnection connection)
        throws InfrastructureException;

    public IConnection getConnection()
        throws InfrastructureException;

    public void makePersistent(T var)
        throws InfrastructureException;

    public void makePersistentUpdate(T var)
        throws InfrastructureException;

    public void makeTransient(T var)
        throws InfrastructureException;

} // .EOF



InfrastructureException.java

package eu.jdevelop.hibernateconnectionwithguice.exceptions;

/**
 * This exception is used to mark (fatal) failures in infrastructure and system code.
 *
 * @author Siegfried Bolz
 */
public class InfrastructureException extends RuntimeException {

  public InfrastructureException() {
  }

  public InfrastructureException(String message) {
    super(message);
  }

  public InfrastructureException(String message, Throwable cause) {
    super(message, cause);
  }

  public InfrastructureException(Throwable cause) {
    super(cause);
  }

} // .EOF



Article.java

package eu.jdevelop.hibernateconnectionwithguice.model;

import java.io.Serializable;

/**
 * Simple Article-Model.
 *
 * @author Siegfried Bolz
 */
public class Article implements Serializable{
    private Long id;
    private String name;
    private double price;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

} // .EOF



Customer.java

package eu.jdevelop.hibernateconnectionwithguice.model;

import java.io.Serializable;

/**
 * Simple Customer-Model.
 *
 * @author Siegfried Bolz
 */
public class Customer implements Serializable{
    private Long id;
    private String name;
    private String street;
    private String city;
    private String postcode;
    private String phone;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getPostcode() {
        return postcode;
    }

    public void setPostcode(String postcode) {
        this.postcode = postcode;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

} // .EOF



Orders.java

package eu.jdevelop.hibernateconnectionwithguice.model;

import java.io.Serializable;
import java.util.Date;

/**
 * Simple Orders-Model.
 *
 * @author Siegfried Bolz
 */
public class Orders implements Serializable {

    private Long id;
    private Customer customer;
    private Article article;
    private int amount;
    private Date orderDate;
    private double sum;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Customer getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public Article getArticle() {
        return article;
    }

    public void setArticle(Article article) {
        this.article = article;
    }

    public int getAmount() {
        return amount;
    }

    public void setAmount(int amount) {
        this.amount = amount;
    }

    public Date getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }

    public double getSum() {
        return sum;
    }

    public void setSum(double sum) {
        this.sum = sum;
    }
} // .EOF


The following three *.hbm.xml -files are in the package: eu.jdevelop.hibernateconnectionwithguice.model

Article.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="eu.jdevelop.hibernateconnectionwithguice.model.Article" table="article">
    <id name="id" column="id">
      <generator class="native" />
    </id>
    <property name="name" column="name" not-null="true" />
    <property name="price" column="price" not-null="true" />
  </class>
</hibernate-mapping>



Customer.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="eu.jdevelop.hibernateconnectionwithguice.model.Customer" table="customer">
    <id name="id" column="id">
      <generator class="native" />
    </id>
    <property name="name" column="name" not-null="true" />
    <property name="street" column="street" not-null="true" />
    <property name="city" column="city" not-null="true" />
    <property name="postcode" column="postcode" not-null="true" />
    <property name="phone" column="phone" not-null="true" />
  </class>
</hibernate-mapping>



Orders.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
  <class name="eu.jdevelop.hibernateconnectionwithguice.model.Orders" table="orders">
    <id name="id" column="id">
      <generator class="native" />
    </id>
    <property name="amount" column="amount" not-null="true" />
    <property name="orderDate" column="orderDate" not-null="true" />
    <property name="sum" column="sum" not-null="true" />
    <many-to-one name="customer" class="eu.jdevelop.hibernateconnectionwithguice.model.Customer" column="customerId" cascade="save-update"/>
    <many-to-one name="article" class="eu.jdevelop.hibernateconnectionwithguice.model.Article" column="articleId" cascade="save-update"/>
  </class>
</hibernate-mapping>



GuiceModule.java

package eu.jdevelop.hibernateconnectionwithguice.modules;

import com.google.inject.AbstractModule;
import com.google.inject.Scopes;
import eu.jdevelop.hibernateconnectionwithguice.dao.impl.HibernateConnection;
import eu.jdevelop.hibernateconnectionwithguice.provider.ConnectionProvider;
import static java.lang.annotation.ElementType.*;


/**
 * Configuration-class for guice. Here are the bindings defined.
 *
 * @author Siegfried Bolz
 */
public class GuiceModule extends AbstractModule{

    @Override
    protected void configure() {

        /**
         * Without the Scopes.SINGLETON, each time wenn you call
         * HibernateConnection connection = injector.getInstance(HibernateConnection.class);
         * a new Instance of HibernateConnection (with the included HibernateUtil) will be created.
         */
        bind(HibernateConnection.class).toProvider(ConnectionProvider.class).in(Scopes.SINGLETON);

    }

} // .EOF



ConnectionProvider.java

package eu.jdevelop.hibernateconnectionwithguice.provider;

import com.google.inject.Provider;
import static java.lang.annotation.ElementType.*;
import com.google.inject.Inject;
import eu.jdevelop.hibernateconnectionwithguice.dao.impl.HibernateConnection;
import eu.jdevelop.hibernateconnectionwithguice.util.HibernateUtil;

/**
 * A simple Provider class that conforms to Guice Provider that creates and
 * return HibernateConnection objects. Guice automatically injects a brand new
 * HibernateUtil-instance (as singleton, defined in class GuiceModule).
 *
 * @author Siegfried Bolz
 */
public class ConnectionProvider implements Provider<hibernateConnection>{

    private final HibernateUtil hibernateUtil;

    @Inject
    ConnectionProvider(HibernateUtil hibernateUtil) {
        this.hibernateUtil = hibernateUtil;
    }


    public HibernateConnection get() {
        HibernateConnection connection = new HibernateConnection(hibernateUtil);
        return connection;
    }

} // .EOF



HibernateUtil.java

package eu.jdevelop.hibernateconnectionwithguice.util;

import eu.jdevelop.hibernateconnectionwithguice.exceptions.InfrastructureException;
import org.hibernate.*;
import org.hibernate.cfg.Configuration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.naming.*;

/**
 * Large Hibernate helper class, handles SessionFactory, Session and Transaction.
 *
 * Uses a  initializer for the initial SessionFactory creation
 * and holds Session and Transactions in thread local variables. All
 * exceptions are wrapped in an unchecked InfrastructureException.
 *
 * @version 1.2
 * @author Siegfried Bolz (www.jdevelop.eu)
 */
public class HibernateUtil {

        /** Logger. */
	private  Log log = LogFactory.getLog(HibernateUtil.class);

	/** configuration. */
	private  Configuration configuration;

	/** Session Factory */
	private  SessionFactory sessionFactory;

	/** JNDI name of sessionfactory. */
	private  final String JNDI_SESSIONFACTORY = "java:hibernate/HibernateFactory";

	/** If running unit tests set to true. */
	private  boolean offlineMode = true;

	/** threadlocal. */
	private  final ThreadLocal threadSession = new ThreadLocal();

	/** threadlocal. */
	private  final ThreadLocal threadTransaction = new ThreadLocal();

	/** threadlocal. */
	private  final ThreadLocal threadInterceptor = new ThreadLocal();

	/** Interceptor class */
	private  final String INTERCEPTOR_CLASS = "hibernate.util.interceptor_class";


	/**
	 * Create the initial SessionFactory from hibernate.xml.cfg or JNDI).
	 * #### Use this Function to initialize Hibernate! ####
	 *
	 * @param offlineMode true=hibernate.cfg.xml , false=JNDI
	 */
	public  void Configure(boolean offlineMode) {
		log.debug("HibernateUtil.Configure() - Trying to initialize Hibernate.");
		try {
			// Use hibernate.cfg.xml (true) or JNDI (false)
			setOfflineMode(offlineMode);
			sessionFactory = getSessionFactory();

		} catch (Throwable x) {
			// We have to catch Throwable, otherwise we will miss
			// NoClassDefFoundError and other subclasses of Error
			log.error("HibernateUtil.Configure() - Building SessionFactory failed.", x);
			throw new ExceptionInInitializerError(x);
		}
	}


    /**
     * Use hibernate.cfg.xml (true) to create sessionfactory or bound
     * sessionfactory to JNDI (false)
     */
    public  void setOfflineMode(boolean mode)
    {
    	if (mode==true)
    	    log.debug("HibernateUtil.setOfflineMode() - Setting mode to hibernate.cfg.xml .");
    	else
    		log.debug("HibernateUtil.setOfflineMode() - Setting mode to JNDI.");

        offlineMode = mode;
    }


        /**
	 * Returns the SessionFactory used for this  class. If offlineMode has
	 * been set then we use hibernate.cfg.xml to create sessionfactory, if not
	 * then we use sessionfactory bound to JNDI.
	 *
	 * @return SessionFactory
	 */
	public  SessionFactory getSessionFactory() {
		if (sessionFactory == null) {
			if (offlineMode == true) {
				log.debug("HibernateUtil.getSessionFactory() - Using hibernate.cfg.xml to create a SessionFactory");
				try {
					configuration = new Configuration();
					sessionFactory = configuration.configure().buildSessionFactory();
				} catch (HibernateException x) {
					throw new InfrastructureException("HibernateUtil.getSessionFactory() - Error creating SessionFactory with hibernate.cfg.xml .",x);
				}

			} else {
				log.debug("HibernateUtil.getSessionFactory() - Using JDNI to create a SessionFactory");
				try {
					Context ctx = new InitialContext();
					sessionFactory = (SessionFactory) ctx.lookup(JNDI_SESSIONFACTORY);
				} catch (NamingException x) {
					throw new InfrastructureException("HibernateUtil.getSessionFactory() - Error creating JNDI-SessionFactory.",x);
				}
			}
		}

		if (sessionFactory == null) {
			throw new IllegalStateException("HibernateUtil.getSessionFactory() - SessionFactory not available.");
		}
		return sessionFactory;
	}


	/**
	 * Sets the given SessionFactory.
	 *
	 * @param sessionFactory
	 */
	public  void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}


        /**
	 * Returns the original Hibernate configuration.
	 *
	 * @return Configuration
	 */
	public  Configuration getConfiguration() {
		return configuration;
	}


        /**
	 * Rebuild the SessionFactory with the  Configuration.
	 *
	 */
	public  void rebuildSessionFactory() throws InfrastructureException {
		log.debug("HibernateUtil.rebuildSessionFactory() - Rebuilding the SessionFactory with the  Configuration.");
		synchronized (sessionFactory) {
			try {
				sessionFactory = getConfiguration().buildSessionFactory();
			} catch (Exception x) {
				throw new InfrastructureException("HibernateUtil.rebuildSessionFactory() - Error rebuilding SessionFactory with the  Configuration",x);
			}
		}
	}


        /**
	 * Rebuild the SessionFactory with the given Hibernate Configuration.
	 *
	 * @param cfg
	 */
	public  void rebuildSessionFactory(Configuration cfg) throws InfrastructureException {
		log.debug("HibernateUtil.rebuildSessionFactory() - Rebuilding the SessionFactory from the given Hibernate Configuration.");
		synchronized (sessionFactory) {
			try {
				if (sessionFactory != null && !sessionFactory.isClosed())
					sessionFactory.close();

				sessionFactory = cfg.buildSessionFactory();
				configuration = cfg;
			} catch (Exception x) {
				throw new InfrastructureException("HibernateUtil.rebuildSessionFactory() - Error rebuilding the SessionFactory with the given Hibernate Configuration",x);
			}
		}
	}


        /**
	 * Destroy this SessionFactory and release all resources (caches, connection
	 * pools, etc).
	 *
	 * @author Siegfried Bolz
	 * @param cfg
	 */
	public  void closeSessionFactory() throws InfrastructureException {
		synchronized (sessionFactory) {
			try {
				log.debug("HibernateUtil.closeSessionFactory() - Destroy the current SessionFactory.");
				sessionFactory.close();
				// Clear  variables
				configuration = null;
				sessionFactory = null;
			} catch (Exception x) {
				throw new InfrastructureException("HibernateUtil.closeSessionFactory() - Error destroying the current SessionFactory",x);
			}
		}
	}


        /**
	 * Retrieves the current Session local to the thread. <p/>
	 *
	 * If no Session is open, opens a new Session for the running thread.
	 *
	 * @return Session
	 */
	public  Session getSession() throws InfrastructureException {
		Session s = (Session) threadSession.get();
		try {
			if (s == null) {
				log.debug("HibernateUtil.getSession() - Opening new Session for this thread.");
				if (getInterceptor() != null) {
					log.debug("HibernateUtil.getSession() - Using interceptor: "+ getInterceptor().getClass());
					s = getSessionFactory().openSession(getInterceptor());
				} else {
					s = getSessionFactory().openSession();
				}
				threadSession.set(s);
			}
		} catch (HibernateException x) {
			throw new InfrastructureException("HibernateUtil.getSession() - Error retrieving/creating a session.",x);
		}
		return s;
	}


        /**
	 * Closes the Session local to the thread.
	 */
	public  void closeSession() throws InfrastructureException {
		try {
			Session s = (Session) threadSession.get();
			threadSession.set(null);
			if (s != null && s.isOpen()) {
				log.debug("HibernateUtil.closeSession() - Closing Session of this thread.");
				s.close();
			}
		} catch (HibernateException x) {
			throw new InfrastructureException("HibernateUtil.closeSession() - Error closing the session.",x);
		}
	}


        /**
	 * Start a new database transaction.
	 */
	public  void beginTransaction() throws InfrastructureException {
		Transaction tx = (Transaction) threadTransaction.get();
		try {
			if (tx == null) {
				log.debug("HibernateUtil.beginTransaction() - Starting new database transaction in this thread.");
				tx = getSession().beginTransaction();
				threadTransaction.set(tx);
			}
		} catch (HibernateException x) {
			throw new InfrastructureException("HibernateUtil.beginTransaction() - Error starting a new database transaction.",x);
		}
	}


        /**
	 * Commit the database transaction.
	 */
	public  void commitTransaction() throws InfrastructureException {
		Transaction tx = (Transaction) threadTransaction.get();
		try {
			if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
				log.debug("HibernateUtil.commitTransaction() - Committing database transaction of this thread.");
				tx.commit();
			}
			threadTransaction.set(null);
		} catch (HibernateException x) {
			rollbackTransaction();
			throw new InfrastructureException("HibernateUtil.commitTransaction() - Error commiting the database transaction.",x);
		}
	}


        /**
	 * Rollback the database transaction.
	 */
	public  void rollbackTransaction() throws InfrastructureException {
		Transaction tx = (Transaction) threadTransaction.get();
		try {
			threadTransaction.set(null);
			if (tx != null && !tx.wasCommitted() && !tx.wasRolledBack()) {
				log.debug("HibernateUtil.rollbackTransaction() - Tyring to rollback database transaction of this thread.");
				tx.rollback();
			}
		} catch (HibernateException x) {
			throw new InfrastructureException("HibernateUtil.rollbackTransaction() - Error rolling back the database transaction.",x);
		} finally {
			closeSession();
		}
	}


        /**
	 * Reconnects a Hibernate Session to the current Thread.
	 *
	 * @param session The Hibernate Session to be reconnected.
	 */
	public  void reconnect(Session session) throws InfrastructureException {
		log.debug("HibernateUtil.reconnect() - Reconnecting Hibernate Session to the current Thread.");
		try {
			session.reconnect(session.connection());
			threadSession.set(session);
		} catch (HibernateException x) {
			throw new InfrastructureException("HibernateUtil.reconnect() - Error reconnectin to the given session.",x);
		}
	}


       /**
	 * Disconnect and return Session from current Thread.
	 *
	 * @return Session the disconnected Session
	 */
	public  Session disconnectSession() throws InfrastructureException {
		log.debug("HibernateUtil.disconnectSession() - Disconnecting Session from current Thread.");
		Session session = getSession();
		try {
			threadSession.set(null);
			if (session.isConnected() && session.isOpen()) {
				session.disconnect();
			}
		} catch (HibernateException x) {
			throw new InfrastructureException("HibernateUtil.disconnectSession() - Error disconnecting session from current thread.",x);
		}
		return session;
	}


       /**
	 * Register a Hibernate interceptor with the current thread.
	 *
	 * Every Session opened is opened with this interceptor after registration.
	 * Has no effect if the current Session of the thread is already open,
	 * effective on next close()/getSession().
	 */
	public  void registerInterceptor(Interceptor interceptor) {
		threadInterceptor.set(interceptor);
	}


        /**
	 * Get Hibernate interceptor.
	 *
	 * @return Interceptor
	 */
	private  Interceptor getInterceptor() {
		Interceptor interceptor = (Interceptor) threadInterceptor.get();
		return interceptor;
	}


        /**
	 * Resets global interceptor to default state.
	 */
	public  void resetInterceptor() {
		log.debug("HibernateUtil.resetInterceptor() - Resetting global interceptor to configuration setting");
		setInterceptor(configuration, null);
	}


        /**
	 * Either sets the given interceptor on the configuration or looks it up
	 * from configuration if null.
	 */
	private  void setInterceptor(Configuration configuration, Interceptor interceptor) {
		String interceptorName = configuration.getProperty(INTERCEPTOR_CLASS);
		if (interceptor == null && interceptorName != null) {
			try {
				log.debug("HibernateUtil.setInterceptor() - Configuring interceptor.");
				Class interceptorClass = HibernateUtil.class.getClassLoader().loadClass(interceptorName);
				interceptor = (Interceptor) interceptorClass.newInstance();
			} catch (Exception x) {
				throw new RuntimeException("HibernateUtil.setInterceptor() - Error, could not configure interceptor: " + interceptorName, x);
			}
		}
		if (interceptor != null) {
			configuration.setInterceptor(interceptor);
		} else {
			configuration.setInterceptor(EmptyInterceptor.INSTANCE);
		}
	}

} // .EOF



Main.java

package eu.jdevelop.hibernateconnectionwithguice;

import eu.jdevelop.hibernateconnectionwithguice.dao.impl.*;
import eu.jdevelop.hibernateconnectionwithguice.model.*;
import com.google.inject.*;
import eu.jdevelop.hibernateconnectionwithguice.controller.OrdersController;
import eu.jdevelop.hibernateconnectionwithguice.modules.GuiceModule;
import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
 * Hibernate with Guice - Part II
 *
 * This is a simple Hibernate-Application which was extended with
 * Guice functionality. To see this Application without Guice,
 * just visit Part I.
 *
 * @author Siegfried Bolz (www.jdevelop.eu)
 */
public class Main {

    private static Log logger = LogFactory.getLog(Main.class);

    public static void main(String[] args) {

        /**
         * There are our bindings defined.
         */
        GuiceModule module = new GuiceModule();


        /**
         * The creation of this injector is something that you would do once, probably upon
         * application startup. The injector is initiated with our bindings.
         */
        Injector injector = Guice.createInjector(new Module[]{module});

        /**
         * The injector injects our controller instance with its dependencies.
         * Our OrdersDAO-instance will be now created.
         */
        OrdersController ordersController = new OrdersController();
        injector.injectMembers(ordersController);


        /**
         * Here we use the Factory to create a HibernateConnection (with its
         * HibernateUtil-reference) instance.
         */
        HibernateConnection connection = injector.getInstance(HibernateConnection.class);
        connection.connect(); // initialize HibernateUtil


        /**
         * Retrieve the previously created instance.
         */
        OrdersDAO dao = ordersController.getOrdersDAO();


        /**
         * Link the HibernateConnection-instance to the OrderDAO-instance.
         * OrderDAO needs this reference to the HibernateUtil.
         */
        dao.setConnection(connection);


        /**
         * Create entities
         */
        Article article1 = new Article();
        article1.setName("iPhone");
        article1.setPrice(399.99);

        Customer customer1 = new Customer();
        customer1.setCity("Munich");
        customer1.setName("Siegfried Bolz");
        customer1.setPhone("555123123");
        customer1.setPostcode("80222");
        customer1.setStreet("Mainstreet 12");

        Orders order1 = new Orders();
        order1.setAmount(1);
        order1.setOrderDate(new Date());
        order1.setSum(article1.getPrice() * order1.getAmount());
        order1.setArticle(article1);
        order1.setCustomer(customer1);


        /**
         * Let OrderDAO handle the persistence.
         */
        dao.makePersistent(order1);


        /**
         * Commit transaction.
         */
        connection.commitTransaction();


        /**
         * Close Hibernate SessionFactory and all sessions.
         */
        connection.disConnect();


        /**
         * ********************* now look if guice handles singleton correctly *************************
         */


        /**
         * Create a new OrdersController but retrieve the same old OrdersDAO-Instance
         * as in line 44 (singleton).
         */
        OrdersController ordersController2 = new OrdersController();
        injector.injectMembers(ordersController2);
        OrdersDAO dao2 = ordersController2.getOrdersDAO();


        /**
         * New database-input.
         */
        Article article2 = new Article();
        article2.setName("MacBook Air");
        article2.setPrice(1799.99);

        Customer customer2 = new Customer();
        customer2.setCity("Kempten");
        customer2.setName("Max Mustermann");
        customer2.setPhone("01714465435");
        customer2.setPostcode("87435");
        customer2.setStreet("Sunset Blv. 6");

        Orders order2 = new Orders();
        order2.setAmount(2);
        order2.setOrderDate(new Date());
        order2.setSum(article2.getPrice() * order2.getAmount());
        order2.setArticle(article2);
        order2.setCustomer(customer2);


        /**
         * Retrieves the same old HibernateConnection-Instance as in line 52 (singleton!).
         */
        HibernateConnection connection2 = injector.getInstance(HibernateConnection.class);

        connection2.connect(); // reconnect to database
        dao2.setConnection(connection2);

        dao2.makePersistent(order2);

        connection2.commitTransaction(); // write in database


        /**
         * get number of orders in database
         */
        logger.info("****** Number of orders in database: " + dao.findAll().size());

        connection2.disConnect(); // finish connection
    }

} // .EOF



The last two files are located at the root of your source-directory.

hibernate.cfg.xml
Take a closer look at this configuration file, if you experience connection-problems to your database.

<?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>

    <!-- Settings for a local MySQL database. -->
    <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
    <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
    <property name="connection.url">jdbc:mysql://localhost:3306/hibernateguicetest</property>
    <property name="connection.username">root</property>
    <property name="connection.password"></property>

    <!-- Print SQL to stdout. -->
    <property name="show_sql">true</property>

    <!-- Mapping files. -->
    <mapping resource="eu/jdevelop/hibernateconnectionwithguice/model/Article.hbm.xml" />
    <mapping resource="eu/jdevelop/hibernateconnectionwithguice/model/Customer.hbm.xml" />
    <mapping resource="eu/jdevelop/hibernateconnectionwithguice/model/Orders.hbm.xml" />

  </session-factory>
</hibernate-configuration>



log4j.properties

log4j.rootLogger=INFO, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x -%m%n



The file structure looks now like this (here from NetBeans 6):
Netbeans 6 - File structure with guice


If you build and run the application, two entites with its sub-entities will be added to your database:
More records in database


Downloads
NetBeans 6 Project Part I: download
NetBeans 6 Project Part II: download
Libaries: download

Further informations
Open existing NetBeans 6 Projects: http://blog.jdevelop.eu/?p=29
Google Guice: http://code.google.com/p/google-guice/
Hibernate: http://www.hibernate.org/


Now you have seen how Guice works and how you can create loose couplings with Dependency Injection. This was my first attempt working with Guice, so i think there are many points which can be improved.

It was hard work to create this examples and writing this blog. If you have any suggestions, feel free to write a comment.

Writing 220-601 is compulsory after 70-291 if you are planning to attempt 646-204 followed by 70-649 or 70-620 and the future goal is 642-901.

Technorati Tags: , , , ,

5 responses so far

5 Responses to “Hibernate with Guice – Part II”

  1. You should check out warp-persist, it is a tiny library (60K) that integrates Hibernate, JPA and db4objects with Guice applications:

    http://www.wideplay.com

    It also provides a powerful query abstraction that lets you get rid of Dao code:

    http://www.wideplay.com/dynamicfinders

    Warp-persist is heavily tested and provides lightweight, guice-style integration.

  2. Siegfried Bolz sagt:

    Thank you for this Information, Warp-Persist looks very great! :-) I will try to use it with this project and create a new blog-entry when i am finished.

  3. [...] http://blog.jdevelop.eu/?p=26Session; /** * Wrapper-class for OrdersDAO (and all other DAO’s). * If you want to use an other HibernateUtil, just change the * ConnectionProvider.class -Binding in GuiceModule or create * other Provider- and Connection classes. … [...]

  4. [...] http://blog.jdevelop.eu/?p=26Session; /** * Wrapper-class for OrdersDAO (and all other DAO’s). * If you want to use an other HibernateUtil, just change the * ConnectionProvider.class -Binding in GuiceModule or create * other Provider- and Connection classes. … [...]

  5. [...] you dont want to use IoC and Google Guice, you can also set up the hibernate utility without Guice. With Guice: Without Guice: I modified the AbstractHibernateConnection class so that it actually uses [...]

Leave a Reply


4 × sieben =