如何用泛型实现Hibernate DAO

时间:2016-06-26 23:44:27

标签: java spring hibernate generics dao

我找到了一些关于如何使用泛型构建Hibernate DAO的教程,但它们都使用EntityManager而不是SessionFactory。我的问题是如何使用SessionFactory使用泛型构建DAO。到目前为止,我有以下内容:

接口:

public interface GenericDao<T> {

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

类别:

@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;
    }

我不确定如何使用泛型来findById。我相信其他方法是正确的,但如果我错了,请纠正我。

侧面问题:使用EntityManager比使用SessionFactory更有益吗?我看到了一些关于这个主题的帖子,但是想要更多的意见。

1 个答案:

答案 0 :(得分:5)

您需要从该方法中访问Class<T>。您有两个选项,可以将Class<T>传递给方法:

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

或者您可以将Class<T>传递给类的构造函数以在方法中使用:

@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
    }
}

子类会将它们的类传递给超类:

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

然后,使用clazz实例,您可以使用Session#get方法获取通用方法中的实体:

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

有关详细信息,请参阅以下问题:

就副问题而言,EntityManager是JPA(Java Persistence API)的一部分。使用Java API规范而不是Hibernate API开发应用程序允许您的应用程序不依赖于Hibernate。这允许您在流行的JPA实现(如Hibernate,OpenJPA或TopLink)之间切换,而无需对代码进行更改和更改。

This question提供了有关差异的更多信息。