Thursday, February 11, 2010

Generic DAO Pattern

Generic DAO Pattern:

In this post I have developed a simple application that how the generic DAO pattern can be used.
Following are the listing.

Directory structure is:

com/sample/

dao/

book/

facory/

hibfactory/

jpafactory/

hibimpl/

book/

jpaimpl/

book/

util/

daoclient/

book/

impl/

book/

domain/


let's first we see our domain object

package com.sample.domain;

public class Book {

private Long id;

private String name;

private String author;

public Book(){

}

public Book(Long id, String name, String author) {

super();

this.id = id;

this.name = name;

this.author = author;

}

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 getAuthor() {

return author;

}

public void setAuthor(String author) {

this.author = author;

}

}

develop also its hbm(use annotation) file.

Generic DAO interface.

package com.sample.dao;

import java.io.Serializable;

import java.util.List;

public interface GenericDAO {

T findById(ID id, boolean lock);

List findAll();

List findByExample(T exampleInstance, String... excludeProperty);

T makePersistent(T entity);

void makeTransient(T entity);

void flush();

void clear();

}

To use hibernate as out persistence provider,


package com.sample.dao.hibimpl;

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;

import com.sample.dao.GenericDAO;

import com.sample.dao.util.HibernateUtil;

public abstract class GenericHibernateDAO implements GenericDAO {

private Class persistentClass;

private Session session;

@SuppressWarnings("unchecked")

public GenericHibernateDAO() {

this.persistentClass = (Class)( (ParameterizedType) getClass().getGenericSuperclass() ).getActualTypeArguments()[0];

}

public void setSession(Session s) {

this.session = s;

}

protected Session getSession() {

if (session == null)

session = HibernateUtil.getCurrentSession();

return session;

}

public Class getPersistentClass() {

return persistentClass;

}

@SuppressWarnings("unchecked")

public T findById(ID id, boolean lock) {

T entity;

if (lock)

entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);

else

entity = (T) getSession()

.load(getPersistentClass(), id);

return entity;

}

@SuppressWarnings("unchecked")

public List findAll() {

return findByCriteria();

}

@SuppressWarnings("unchecked")

public List 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();

}

/**

* Use this inside subclasses as a convenience method.

*/

@SuppressWarnings("unchecked")

protected List findByCriteria(Criterion... criterion) {

Criteria crit = getSession().createCriteria(getPersistentClass());

for (Criterion c : criterion) {

crit.add(c);

}

return crit.list();

}

}


if want to JPA as the provider


package com.sample.dao.jpaimpl;

import java.io.Serializable;

import com.sample.dao.GenericDAO;

public abstract class GenericJpaDAO implements GenericDAO{

// Methods specific to jpa implementation............

}

Using hibernate implementation.

package com.sample.dao.hibimpl.book;

import com.sample.dao.book.BookDAO;

import com.sample.dao.hibimpl.GenericHibernateDAO;

import com.sample.domain.Book;

/**

* @author Khursheed Ahmed

*

*/

public class BookDAOImpl extends GenericHibernateDAO implements BookDAO{

public Book findBook(Long id) {

/*your hql query to find book*/

return null;

}

}
now to develop our dao client, before developing our dao client develop a factory for getting you dao in dao client.

package com.sample.dao.factory;

import com.sample.dao.book.BookDAO;

import com.sample.dao.factory.hibfactory.HibernateDAOFactory;

import com.sample.dao.factory.jpafactory.JpaDAOFactory;

public abstract class DAOFactory {

public static enum DAOFactoryType {Hibernate, Jpa, };

public static DAOFactory instance(DAOFactoryType factoryType) {

DAOFactory factory = null;

try {

switch (factoryType) {

case Hibernate:

factory = HibernateDAOFactory.class.newInstance();

break;

case Jpa:

factory = JpaDAOFactory.class.newInstance();

break;

default:

factory = HibernateDAOFactory.class.newInstance();

break;

}

return factory;

} catch (Exception ex) {

throw new RuntimeException("Couldn't create DAOFactory for : " + factoryType);

}

}

@SuppressWarnings("unchecked")

public static DAOFactory instance(Class factory) {

try {

return (DAOFactory)factory.newInstance();

} catch (Exception ex) {

throw new RuntimeException("Couldn't create DAOFactory for : " + factory);

}

}

// Add your DAO interfaces here

public abstract BookDAO getBookDAO();

}


Develop factory to our specific provider


package com.sample.dao.factory.hibfactory;

import com.sample.dao.book.BookDAO;

import com.sample.dao.factory.DAOFactory;

import com.sample.dao.hibimpl.GenericHibernateDAO;

import com.sample.dao.hibimpl.book.BookDAOImpl;

public class HibernateDAOFactory extends DAOFactory {

@SuppressWarnings("unchecked")

private GenericHibernateDAO instantiateDAO(Class daoClass) {

try {

GenericHibernateDAO dao = (GenericHibernateDAO)daoClass.newInstance();

return dao;

} catch (Exception ex) {

throw new RuntimeException(

"Can not instantiate DAO: " + daoClass, ex);

}

}

/* (non-Javadoc)

* @see com.sample.dao.factory.DAOFactory#getBookDAO()

*/

@Override

public BookDAO getBookDAO() {

return (BookDAO) instantiateDAO(BookDAOImpl.class);

}

}

package com.sample.dao.factory.jpafactory;

import com.sample.dao.book.BookDAO;

import com.sample.dao.factory.DAOFactory;

import com.sample.dao.hibimpl.book.BookDAOImpl;

import com.sample.dao.jpaimpl.GenericJpaDAO;

public class JpaDAOFactory extends DAOFactory {

@SuppressWarnings("unchecked")

private GenericJpaDAO instantiateDAO(Class daoClass) {

try {

GenericJpaDAO dao = (GenericJpaDAO)daoClass.newInstance();

return dao;

} catch (Exception ex) {

throw new RuntimeException(

"Can not instantiate DAO: " + daoClass, ex);

}

}

/* (non-Javadoc)

* @see com.sample.dao.factory.DAOFactory#getBookDAO()

*/

@Override

public BookDAO getBookDAO() {

return (BookDAO) instantiateDAO(BookDAOImpl.class);

}

}



now our dao client.


package com.sample.daoclient.book;
import com.sample.domain.Book;

public interface BookManager {

void addBook(Book book);

void deleteBook(Long id);

/* more methods.....*/

}

import com.sample.dao.book.BookDAO;

import com.sample.dao.factory.DAOFactory;
import com.sample.dao.factory.hibfactory.HibernateDAOFactory;
import com.sample.daoclient.book.BookManager;
import com.sample.domain.Book;

public class BookManagerImpl implements BookManager {

private BookDAO bookDAO;


public BookManagerImpl(){

/*DAOFactory factory = DAOFactory.instance(DAOFactory.DAOFactoryType.Hibernate);*/

DAOFactory factory = DAOFactory.instance(HibernateDAOFactory.class);

bookDAO = factory.getBookDAO();
}
public BookDAO getBookDAO() {return bookDAO;}

public void setBookDAO(BookDAO bookDAO) {this.bookDAO = bookDAO;}

public void addBook(Book book){bookDAO.makePersistent(book);}

public void deleteBook(Long id ){

Book book = new Book();

book.setId(id);

bookDAO.makeTransient(book);

}

}

Finally here is HibernateUtil

package com.sample.dao.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

private static Configuration configuration = new Configuration();
private static SessionFactory sessionFactory;

private static ThreadLocal sessions = new ThreadLocal();


static {

try {

sessionFactory = configuration.configure("hibernate.cfg.xml").buildSessionFactory();

} catch (Throwable ex) {

ex.printStackTrace();

throw new ExceptionInInitializerError(ex);

}

}

public static SessionFactory getSessionFactory() {

// Alternatively, you could look up in JNDI here

return sessionFactory;
}

public static void shutdown() {

// Close caches and connection pools

getSessionFactory().close();

}

public static Session getCurrentSession(){

Session session = (Session) sessions.get();

if (session == null || !session.isOpen()) {

if (sessionFactory == null) {

rebuildSessionFactory();

}
session = (sessionFactory != null) ?

sessionFactory.openSession() : null;

sessions.set(session);
}

return session;

}

public static void rebuildSessionFactory() {

try {

sessionFactory = configuration.configure("hibernate.cfg.xml").buildSessionFactory();

} catch (Exception e) {

System.err.println("%%%% Error Creating SessionFactory %%%%");

e.printStackTrace();

}

}

public static Configuration getConfiguration() {

return configuration;

}

}


References:
https://www.hibernate.org/328.html

No comments:

Post a Comment