工作三年了,想把自己接触过的,以及将要接触的一些知识技能做些整理。因此,开始着手长期开发一个纯技术性的生态系统——j2eelib,顾名思义,里面的各模块,和j2ee相关。
今天要说的是其中和MVC相关的部分——自己设计的一个DAO模式,用于数据库访问层。
首先,关于dao层相关的包结构,如下图所示。
该包结构可以看出,这套DAO模式存在两个体系。其一是application包下的应用级体系,其二是framework包下的框架级体系。
一般而言,对于一个需要进行数据库访问的dao,比如截图中对user实体进行操作的dao,笔者认为存在这样一种继承体系思考原则:对于上层的bo层或service层,需要注入相应的userDAO属性用于数据库访问。而userDAO可以是hibernate实现,也可以是jdbc实现,或者是ibatis实现。但各种实现,都需要有一个通用的接口,使得bo层userBO能够无差别的去调用。因此在application包下存在一个IUserDAO接口,而下面的UserHibernateDAO和UserJdbcDAO分别是其下两种实现。可在属性注入时注入到bo中。
IUserDAO的代码如下所示:
import com.wantall.application.mvc.po.User;
import com.wantall.framework.mvc.dao.interfaces.IBaseDAO;
public interface IUserDAO extends IBaseDAO<User> {
//void test(User user);
}
作为一个简单的application应用,IUserDAO没有太多的业务方法,而仅仅是继承了另一个framework包下的IBaseDAO,这个类的存在是为了给所有的DAO业务接口提供一个基本的操作规范,其代码如下所示:
import java.io.Serializable;
import java.util.List;
public interface IBaseDAO<T> {
public int insert(T obj);
public int delete(Serializable id);
public int delete(T obj);
public int update(T obj);
public T queryOneByID(Serializable id);
public List<T> queryAllForList();
}
下面从具体技术实现角度继续说明。
对于IUserDAO的实现,如UserHibernateDAO,代码如下所示:
import java.io.Serializable;
import java.util.List;
import com.wantall.application.mvc.dao.interfaces.IUserDAO;
import com.wantall.application.mvc.po.User;
import com.wantall.framework.mvc.daosupport.hibernate.interfaces.IHibernateDAOSupport;
public class UserHibernateDAO implements IUserDAO {
private IHibernateDAOSupport<User> hibernateDAOSupport;
public int delete(Serializable id) {
User user = new User();
hibernateDAOSupport.hibDelete(user);
return 0;
}
public int delete(User user) {
hibernateDAOSupport.hibDelete(user);
return 0;
}
public int insert(User user) {
hibernateDAOSupport.hibInsert(user);
return 0;
}
public List<User> queryAllForList() {
return hibernateDAOSupport.hibQueryAllForList(User.class);
}
public User queryOneByID(Serializable id) {
return hibernateDAOSupport.hibQuery(User.class, id);
}
public int update(User user) {
hibernateDAOSupport.hibUpdate(user);
return 0;
}
public void test(User user) {
//测试脱管后无缓存
insert(user);
//super.getSessionFactory().evict(user.getClass());
//hibernateDAOSupport.getSessionFactory().getCurrentSession().evict(user);
queryOneByID(user.getId());
}
}
对此需要说明的是,其中存在一个hibernateDAOSupport属性。该属性告诉我们,该类是一个基于hibernate的数据库访问类。而hibernateDAOSupport属性是一个support层级的接口。笔者考虑到hibernate的实现有多种,可以是原生hibernate的操作,也可以是基于spring中的hibernateDAOSupport实现,也可以是spring中的hibernateTemplate实现,因此这里通过hibernateDAOSupport接口,屏蔽了实现细节的多样性。其代码如下:
import java.io.Serializable;
import java.util.List;
public interface IHibernateDAOSupport<T> {
public void hibInsert(T obj);
/**
* 删除
* 该方法必须要先查出T obj
* @param id
*/
public void hibDelete(Class<T> cl, Serializable id);
/**
* 删除
* 该方法可以删除一个new出来的对象 无需先查出
* @param obj
*/
public void hibDelete(T obj);
public void hibUpdate(T obj);
public int excuteUpdateHQL(String hql, Object[] params);
public T hibQuery(Class<T> cl, Serializable id);
public List<T> hibQueryAllForList(Class<T> cl);
@SuppressWarnings("unchecked")
public List<T> executeListQuery(String hql, Object... Params);
/**
* 简单hql查询,获取出的不一定是对象,可能是属性集合
* @param hql
* @return
*/
@SuppressWarnings("unchecked")
public List<T> hibCommonQuery(String hql);
}
而为了说明这种support的继承体系,以其实现类HibernateDAOSupport的代码进行说明:
import java.io.Serializable;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import com.wantall.framework.mvc.daosupport.hibernate.interfaces.IHibernateDAOSupport;
public class HibernateDAOSupport<T> extends HibernateDaoSupport implements IHibernateDAOSupport<T> {
public void hibInsert(T obj) {
getHibernateTemplate().save(obj);
getHibernateTemplate().flush();
}
/**
* 删除
* 该方法必须要先查出T obj
* @param id
*/
public void hibDelete(Class<T> cl, Serializable id) {
T obj = hibQuery(cl, id);
if(obj != null) hibDelete(obj);
}
/**
* 删除
* 该方法可以删除一个new出来的对象 无需先查出
* @param obj
*/
public void hibDelete(T obj) {
getHibernateTemplate().delete(obj);
getHibernateTemplate().flush();
}
public void hibUpdate(T obj) {
getHibernateTemplate().merge(obj);
getHibernateTemplate().flush();
}
public int excuteUpdateHQL(String hql, Object[] params) {
int result = 0;
Session session = null;
Query query = null;
Transaction tx = null;
try {
session = getSession();
tx = session.beginTransaction();
query = session.createQuery(hql);
for(int i = 0 ; i < params.length ; i ++ ) {
query.setParameter(i, params[i]);
}
result = query.executeUpdate();
tx.commit();
} catch(Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
session.close();
return result;
}
}
public T hibQuery(Class<T> cl, Serializable id) {
return (T) getHibernateTemplate().get(cl, id);
}
public List<T> hibQueryAllForList(Class<T> cl) {
return this.getHibernateTemplate().loadAll(cl);
}
@SuppressWarnings("unchecked")
public List<T> executeListQuery(String hql, Object... Params) {
if (Params == null || Params.length == 0) {
return this.getHibernateTemplate().find(hql);
}
return this.getHibernateTemplate().find(hql, Params);
}
/**
* 简单hql查询,获取出的不一定是对象,可能是属性集合
* @param hql
* @return
*/
@SuppressWarnings("unchecked")
public List<T> hibCommonQuery(String hql) {
Query query = this.getSession().createQuery(hql);
return query.list();
}
}
该类的实现是基于spring的hibernateDaoSupport的。
以上通过一个user的数据库访问操作,大致说明了j2eelib中数据库访问的一套基本机制,通过hibernate实现进行了简单介绍。本文强调的是设计观念, 因此在具体的实现类中,也会存在一些不完善的代码,或在IBaseDAO中缺乏一些笔者未曾想到的基本方法。大家可以指出哦(毕竟是技术交流嘛)。
后续将继续介绍j2eelib中MVC设计中的其他相关设计。