Jake Miller Jake Miller - 5 months ago 26
Java Question

How to implement Hibernate DAO with generics

I've found a few tutorials on how to build a Hibernate DAO with generics, but they all use

EntityManager
instead of a
SessionFactory
. My question is how to build a DAO with generics using
SessionFactory
. I have the below so far:

Interface:

public interface GenericDao<T> {

public void save(T obj);
public void update(T obj);
public void delete(T obj);
public T findById(long id);
}


Class:

@Repository
public class GenericDaoImpl<T> implements GenericDao<T> {

@Autowired
private SessionFactory sessionFactory;

public void save(T obj) {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(obj);
tx.commit();
} catch (HibernateException e) {
if(tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}

}

public void update(T obj) {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.update(obj);
tx.commit();
} catch (HibernateException e) {
if(tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}

}

public void delete(T obj) {
Session session = sessionFactory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.delete(obj);
tx.commit();
} catch (HibernateException e) {
if(tx != null)
tx.rollback();
e.printStackTrace();
} finally {
session.close();
}

}

public T findById(long id) {
// ??
return null;
}


I'm unsure how to go about
findById
using generics. I believe the other methods are right, but correct me if I'm wrong.

SIDE QUESTION: Is using
EntityManager
more beneficial than using
SessionFactory
? I saw a few posts on the subject, but would like a few more opinions.

Answer

You need to have access to the Class<T> from within that method. You have two options, you can pass the Class<T> into the method:

public T findById(long id, Class<T> clazz) {
    // method implementation
}

Or you can pass the Class<T> into the constructor of the class for use in the method:

@Repository
public class GenericDaoImpl<T> implements GenericDao<T> {

    private Class<T> clazz;

    protected GenericDaoImpl(Class<T> clazz) {
        this.clazz = clazz;
    }

    // other methods omitted

    public T findById(long id) {
        // method implementation
    }
}

And subclasses would pass their class into the superclass:

public class UserDao extends GenericDaoImpl<User> {
    public UserDao() {
        super(User.class);
    }
}

Then, using your clazz instance you can get the entity in your generic method using the Session#get method:

T entity = session.get(clazz, id);

See the following questions for more information:


As far as the side question, the EntityManager is part of JPA (the Java Persistence API). Developing your application using the Java API specification instead of the Hibernate API allows your application to not become dependent on Hibernate. This allows you to switch between popular JPA implementations like Hibernate, OpenJPA, or TopLink without making and changes to your code.

This question has more information on the difference.

Comments