DaoFactory的设计

本打算在网上找一些资源的,可是发现大多数人都是用的hibernate,对于DaoFacotry并不需要过多的考虑。

后来突然想到个办法,干脆直接去看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类型的使用,许多的重复代码。 可以考虑下能不能通过反射来解决。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值