Novembre 16, 2019

DAO Factory pattern e Hibernate

Hibernate è un ORM framework java che permette non solo di isolare in un solo livello la logica di persistenza dei dati, ma facilita anche le complesse attività di creazione, prelievo, aggiornamento ed eliminazione dei dati. In un precedente articolo, ho mostrato come integrare Hibernate in un progetto web Struts MVC. Una volta completata la configurazione minimale del framework, è possibile combinare i design pattern DAO e Factory con Hibernate per ottenere una più avanzata e astratta implementazione dello strato di persistenza di un’applicazione web. Per fare questo userò l’ottimo esempio postato su CaveatEmptor. Ecco un diagramma delle classi ad alto livello della soluzione adottata.

 

dao-factory-hibernate-class-diagram

SOURCE CODE (/giuseu/struts-mvc)

GIT
git clone https://gitlab.com/giuseppeurso-eu/struts-mvc

Dopo aver creato un progetto web dinamico e installato Hibernate (vedi qui) possiamo procedere all’implementazione della Factory.

– DAOFactory

package com.demo.hibernate;

public abstract class DAOFactory {

    /**
     * Creates a standalone DAOFactory that returns unmanaged DAO
     * beans for use in any environment Hibernate has been configured
     * for. Uses HibernateUtil/SessionFactory and Hibernate context
     * propagation (CurrentSessionContext), thread-bound or transaction-bound,
     * and transaction scoped.
     */
    public static final Class HIBERNATE = DAOHibernateFactory.class;

    /**
     * Factory method for instantiation of concrete factories.
     */
    public static DAOFactory instance(Class factory) {
        try {
            return (DAOFactory)factory.newInstance();
        } catch (Exception ex) {
            throw new RuntimeException("Couldn't create DAOFactory: " + factory);
        }
    }

    // Add your DAO interfaces here
}

 

– DAOHibernateFactory

package com.demo.hibernate;

import org.hibernate.Session;

public class DAOHibernateFactory extends DAOFactory {

    private GenericHibernateDAO instantiateDAO(Class daoClass) {
        try {
            GenericHibernateDAO dao = (GenericHibernateDAO)daoClass.newInstance();
            dao.setSession(getCurrentSession());
            return dao;
        } catch (Exception ex) {
            throw new RuntimeException("Can not instantiate DAO: " + daoClass, ex);
        }
    }

    // You could override this if you don't want HibernateUtil for lookup
    protected Session getCurrentSession() {
        return SessionUtil.getSessionFactory().getCurrentSession();
    }

}

Aggiungiamo ora l’interfaccia DAO e una sua implementazione con i metodi fondamentali per le operazioni di CRUD.

– GenericDAO

package com.demo.hibernate;

import java.io.Serializable;
import java.util.List;

public interface GenericDAO<T, ID extends Serializable> {

    T findById(ID id, boolean lock);

    List<T> findAll();

    List<T> findByExample(T exampleInstance, String[] excludeProperty);

    T makePersistent(T entity);

    void makeTransient(T entity);

}

– GenericHibernateDAO

package com.demo.hibernate;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Example;

public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> {

	private Class<T> persistentClass;
	private Session session;

	public GenericHibernateDAO() {
		this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	@SuppressWarnings("unchecked")
	public void setSession(Session s) {
		this.session = s;
	}

	protected Session getSession() {
		if (session == null)
		    throw new IllegalStateException("Session has not been set on DAO before usage");
		return session;
	}

	public Class<T> getPersistentClass() {
		return persistentClass;
	}

	@SuppressWarnings("unchecked")
	public T findById(ID id, boolean lock) {
		T entity;
		if (lock)
			//entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
			entity = (T) getSession().get(getPersistentClass(), id, LockMode.UPGRADE);
		else
		    //entity = (T) getSession().load(getPersistentClass(), id);
			entity = (T) getSession().get(getPersistentClass(), id);
	return entity;
}

	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		return findByCriteria();
	}

	@SuppressWarnings("unchecked")
	public List<T> findByExample(T exampleInstance, String[] excludeProperty) {
		Criteria crit = getSession().createCriteria(getPersistentClass());
		Example example =  Example.create(exampleInstance);
		for (String exclude : excludeProperty) {
		    example.excludeProperty(exclude);
		}
		crit.add(example);
		return crit.list();
	}

	@SuppressWarnings("unchecked")
		public T makePersistent(T entity) {
		getSession().saveOrUpdate(entity);
		return entity;
	}

	public void makeTransient(T entity) {
		getSession().delete(entity);
	}

	public void flush() {
		getSession().flush();
	}

	public void clear() {
		getSession().clear();
	}

}

Il layout di progetto si presenta così

dao-factory-hibernate-project-layout

Related posts

Leave a Reply

Your email address will not be published.