如何使用泛型实现 Hibernate DAO
How to implement Hibernate DAO with generics
我找到了一些关于如何使用泛型构建 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);
}
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;
}
我不确定如何 findById
使用泛型。我相信其他的方法都是对的,如果我错了请指正。
附带问题: 使用 EntityManager
是否比使用 SessionFactory
更有益?我看到了一些关于这个主题的帖子,但还想听听更多的意见。
您需要从该方法中访问 Class<T>
。您有两个选择,您可以将 Class<T>
传递到方法中:
public T findById(long id, Class<T> clazz) {
// method implementation
}
或者您可以将 Class<T>
传递到 class 的构造函数中以在方法中使用:
@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
}
}
而 subclasses 会将它们的 class 传递给 superclass:
public class UserDao extends GenericDaoImpl<User> {
public UserDao() {
super(User.class);
}
}
然后,使用您的 clazz
实例,您可以使用 Session#get 方法在通用方法中获取实体:
T entity = session.get(clazz, id);
有关详细信息,请参阅以下问题:
- How to get a class instance of generics type T
- Get object by ID in Hibernate
至于附带问题,EntityManager
是 JPA 的一部分(Java 持久性 API)。使用 Java API 规范而不是 Hibernate API 开发您的应用程序可以让您的应用程序不依赖于 Hibernate。这允许您在 Hibernate、OpenJPA 或 TopLink 等流行的 JPA 实现之间切换,而无需对代码进行更改。
This question 有更多关于差异的信息。
我找到了一些关于如何使用泛型构建 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);
}
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;
}
我不确定如何 findById
使用泛型。我相信其他的方法都是对的,如果我错了请指正。
附带问题: 使用 EntityManager
是否比使用 SessionFactory
更有益?我看到了一些关于这个主题的帖子,但还想听听更多的意见。
您需要从该方法中访问 Class<T>
。您有两个选择,您可以将 Class<T>
传递到方法中:
public T findById(long id, Class<T> clazz) {
// method implementation
}
或者您可以将 Class<T>
传递到 class 的构造函数中以在方法中使用:
@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
}
}
而 subclasses 会将它们的 class 传递给 superclass:
public class UserDao extends GenericDaoImpl<User> {
public UserDao() {
super(User.class);
}
}
然后,使用您的 clazz
实例,您可以使用 Session#get 方法在通用方法中获取实体:
T entity = session.get(clazz, id);
有关详细信息,请参阅以下问题:
- How to get a class instance of generics type T
- Get object by ID in Hibernate
至于附带问题,EntityManager
是 JPA 的一部分(Java 持久性 API)。使用 Java API 规范而不是 Hibernate API 开发您的应用程序可以让您的应用程序不依赖于 Hibernate。这允许您在 Hibernate、OpenJPA 或 TopLink 等流行的 JPA 实现之间切换,而无需对代码进行更改。
This question 有更多关于差异的信息。