本打算在网上找一些资源的,可是发现大多数人都是用的hibernate,对于DaoFacotry并不需要过多的考虑。
后来突然想到个办法,干脆直接去看Hibernate的代码,看看它是怎么设计DaoFactory的。 结果却在Hibernate官网上看到了一篇关于数据持久层的文章,觉得对我的设计应该还是有帮助的。
原文地址:https://www.hibernate.org/328.html
有关Dao接口的设计:
这样的设计号称是面向状态的数据库持久层的标准模式,原话这样讲的:
You can already see that this is going to be a pattern for a state-oriented data access API, with methods such as makePersistent() and makeTransient(). Furthermore, to implement a DAO you have to provide a type and an identifier argument. As for most ORM solutions, identifier types have to be serializable.
接下来是添加实体DAO接口:
其实对于Hibernate来说,因为HQL的引入,实体Dao接口并不是必须的。而如果不使用Hibernate,那么其实最好是加入实体Dao接口,以便将来对于其它数据库的支持。
Hibernate中对于BaseDao接口的实现方法:
这里我们需要关心下,究竟如何注入Session,是用setter方法,还是在构造函数中注入。你的后台数据库连接的管理方式,决定着哪中方法是最合适的。
接下来就是实体Dao的设计,很简单:
具体DaoFactory的实现:
其实这篇文章还是主要讲怎么在Hibernate里面用做数据持久层,不过也可以从中得到很多借鉴。
因为持久层的设计没有采用Hibernate,遇到挺多问题,包括Object类型的使用,许多的重复代码。 可以考虑下能不能通过反射来解决。
后来突然想到个办法,干脆直接去看Hibernate的代码,看看它是怎么设计DaoFactory的。 结果却在Hibernate官网上看到了一篇关于数据持久层的文章,觉得对我的设计应该还是有帮助的。
原文地址:https://www.hibernate.org/328.html
有关Dao接口的设计:
public interface GenericDAO<T, ID extends Serializable> {
T findById(ID id, boolean lock);
List<T> findAll();
List<T> findByExample(T exampleInstance);
T makePersistent(T entity);
void makeTransient(T entity);
}
这样的设计号称是面向状态的数据库持久层的标准模式,原话这样讲的:
You can already see that this is going to be a pattern for a state-oriented data access API, with methods such as makePersistent() and makeTransient(). Furthermore, to implement a DAO you have to provide a type and an identifier argument. As for most ORM solutions, identifier types have to be serializable.
接下来是添加实体DAO接口:
public interface ItemDAO extends GenericDAO<Item, Long> {
public static final String QUERY_MAXBID = "ItemDAO.QUERY_MAXBID";
public static final String QUERY_MINBID = "ItemDAO.QUERY_MINBID";
Bid getMaxBid(Long itemId);
Bid getMinBid(Long itemId);
}
其实对于Hibernate来说,因为HQL的引入,实体Dao接口并不是必须的。而如果不使用Hibernate,那么其实最好是加入实体Dao接口,以便将来对于其它数据库的支持。
Hibernate中对于BaseDao接口的实现方法:
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);
else
entity = (T) getSession().load(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();
}
/**
* Use this inside subclasses as a convenience method.
*/
@SuppressWarnings("unchecked")
protected List<T> findByCriteria(Criterion... criterion) {
Criteria crit = getSession().createCriteria(getPersistentClass());
for (Criterion c : criterion) {
crit.add(c);
}
return crit.list();
}
}
这里我们需要关心下,究竟如何注入Session,是用setter方法,还是在构造函数中注入。你的后台数据库连接的管理方式,决定着哪中方法是最合适的。
接下来就是实体Dao的设计,很简单:
public class ItemDAOHibernate
extends GenericHibernateDAO<Item, Long>
implements ItemDAO {
public Bid getMaxBid(Long itemId) {
Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID);
q.setParameter("itemid", itemId);
return (Bid) q.uniqueResult();
}
public Bid getMinBid(Long itemId) {
Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID);
q.setParameter("itemid", itemId);
return (Bid) q.uniqueResult();
}
}
具体DaoFactory的实现:
public class HibernateDAOFactory extends DAOFactory {
public ItemDAO getItemDAO() {
return (ItemDAO)instantiateDAO(ItemDAOHibernate.class);
}
public CategoryDAO getCategoryDAO() {
return (CategoryDAO)instantiateDAO(CategoryDAOHibernate.class);
}
public CommentDAO getCommentDAO() {
return (CommentDAO)instantiateDAO(CommentDAOHibernate.class);
}
public ShipmentDAO getShipmentDAO() {
return (ShipmentDAO)instantiateDAO(ShipmentDAOHibernate.class);
}
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 HibernateUtil.getSessionFactory().getCurrentSession();
}
// Inline concrete DAO implementations with no business-related data access methods.
// If we use public static nested classes, we can centralize all of them in one source file.
public static class CommentDAOHibernate
extends GenericHibernateDAO<Comment, Long>
implements CommentDAO {}
public static class ShipmentDAOHibernate
extends GenericHibernateDAO<Shipment, Long>
implements ShipmentDAO {}
}
其实这篇文章还是主要讲怎么在Hibernate里面用做数据持久层,不过也可以从中得到很多借鉴。
因为持久层的设计没有采用Hibernate,遇到挺多问题,包括Object类型的使用,许多的重复代码。 可以考虑下能不能通过反射来解决。