首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 开源软件 >

struts2+spring3+hibernate4调整(3)-包的组织和DAO层的重构

2013-03-25 
struts2+spring3+hibernate4整合(3)---包的组织和DAO层的重构? ? ? ? ?在这里稍作解释即可:src下的com.zq

struts2+spring3+hibernate4整合(3)---包的组织和DAO层的重构

? ? ? ? ?在这里稍作解释即可:src下的com.zq下有两个包,分别是common和demo。common中放的都是整个项目中公用的部分,比如po(model),dao,daoImpl,service,serviceImpl,web,util。其中web中又可以分为action,filter,listener等,对于不同的架构ssh或者其他web框架,包的组织是可变的。demo是一个示例性的包,其内容和common中几乎是一样的,在以后的开发中,这个demo相当于一个模块,比如对于一个hr的项目来说,可以是薪资模块,档案模块等。test是我自己写单元测试的一个文件夹,放在这里不甚规范,大家可以视而不见。然后剩下的就是配置文件了。system-config.properties是系统必要的一些配置。

这种包的组织方式结构清晰,可以立刻定位到发生错误的模块和代码,也易于维护。

? ? ? ? ? 二、DAO层的重构。

? ? ? ? 先回顾一下java中的一些概念:

? ? ? ? 继承:为什么要抽象出父类来继承呢?简单的说,继承是为了代码的复用,把一些重复性的代码提取出来,凡是继承我的子类都可以共享。比如你老爸有辆车,你是你老爸的儿子,你继承了你老爸的家产,所以这辆车你就可以开。

? ? ? ? 接口:为什么要抽象出接口去实现?抽象接口的过程就是制定规范的过程,最好的例子就是JDBC。我要连接数据库,就得有Connection,而oracle,SQLServer各个数据库厂商就得去提供这样的实现,才JDBC才能“一统江湖”。

? ? ? ? 先上一个图,在战略上藐视一下这个结构(电脑上没有UML的工具,是我用ppt搞的一个图):

?


struts2+spring3+hibernate4调整(3)-包的组织和DAO层的重构
?

首先有一个老大接口,他是所有DAO的祖宗,里面有所有DAO通用的一些方法,比如save啦,delete啦等。

然后各个DAO还有自己一些独特的方法,比如根据在一个网上商城的项目中,需要根据用户的ID去查询该用户所有的送货地址。这个功能是某个DAO独有的,那怎么办呢?简单!创建一个DAO(图中的XXXDAO),让他去继承IBaseDAO,通用的方法也继承过来了,特有的方法也定义好了,nice~

然后有了一个“特立独行的DAO(XXXDAO)”之后,我们就需要去实现啦!怎么实现呢?写个DAO的实现类就成了呗!可是问题又来了,用什么技术去实现呢,hibernate?mybatis?还是原生JDBC呢?要是项目经理说:hibernate最能满足咱们的需求,咱们就用hibernate吧!好嘞,咱们就用hibernate,于是就有了XXXHibernateDAO,但是接口继承了接口,里面需要去实现的方法太多了!少说也得十多个,而且就那些重复的代码也太多了吧,烦死人了。于是乎,BaseHibernateDAO横空出世。它是干嘛的呢?他就是帮助你少写代码的好帮手啊,让他去实现IBaseDAO里面的方法,然后被XXXHibernateDAO继承,这样不久不用去实那些通用方法了吗,那些通用方法被BaseHibernateDAO搞定啦!XXXHibernateDAO需要做的就是去实现那些“特立独行”的方法就可以啦!这样又少了很多工作量,perfect!

? ? ? ? 说了这么多理论的东西,都快晕了,贴上代码,满满去体味吧。

先来个实体类PO:Customer:

?

package com.zq.demo.po;import javax.persistence.*;import java.io.Serializable;import java.util.Date;@Entity@Table(name="customer")public class Customer implements Serializable {    private long dbid;    private String name;    private String pwd;    private Date birthday;    public Customer() {    }    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    public long getDbid() {        return dbid;    }    public void setDbid(long dbid) {        this.dbid = dbid;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getPwd() {        return pwd;    }    public void setPwd(String pwd) {        this.pwd = pwd;    }    public Date getBirthday() {        return birthday;    }    public void setBirthday(Date birthday) {        this.birthday = birthday;    }}

?然后重点推荐:IBaseDAO

?

package com.zq.common.dao;import java.io.Serializable;import java.util.List;public interface IBaseDAO<M extends Serializable> {    public long save(M model);    public void saveOrUpdate(M model);    public void update(M model);    public void delete(long id);    public void deleteObject(M model);    public M get(long id);    public int countAll();    public List<M> listAll();    public List<M> listAll(int start, int limit);    boolean exists(long id);    public void flush();    public void clear();}

?然后在看看他的hibernate的实现:BaseHibernateDAO

package com.zq.common.dao.hibernate;import com.zq.common.dao.IBaseDAO;import org.hibernate.Query;import org.hibernate.SQLQuery;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.hibernate.transform.Transformers;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import javax.persistence.Id;import java.io.Serializable;import java.lang.reflect.Field;import java.lang.reflect.ParameterizedType;import java.util.Date;import java.util.List;import java.util.Map;@Component("baseHibernateDAO")public abstract class BaseHibernateDAO<M extends Serializable> implements IBaseDAO<M> {    @Autowired    @Qualifier("sessionFactory")  //按名字自动输入,省略setter和getter方法    private SessionFactory sessionFactory;    private final Class<M> entityClass;    private final String HQL_LIST_ALL;    private final String HQL_COUNT_ALL;    private String pkName = null;    @SuppressWarnings("unchecked")    public BaseHibernateDAO() {        /*        * getClass().getGenericSuperclass()返回表示此 Class 所表示的实体(类、接口、基本类型或 void)的直接超类的 Type        * 然后将其转换ParameterizedType。 getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。        * [0]就是这个数组中第一个了。 简而言之就是获得超类的泛型参数的实际类型。        *        * */        this.entityClass = (Class<M>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];        Field fields[] = this.entityClass.getDeclaredFields();        for (Field field : fields) {            if (field.isAnnotationPresent(Id.class)) {                this.pkName = field.getName();            }        }        //Assert.notNull(pkName);        HQL_LIST_ALL = "from " + this.entityClass.getSimpleName() + " order by " + pkName + " desc";        HQL_COUNT_ALL = " select count(*) from " + this.entityClass.getSimpleName();    }    public Session getSession() {        //事务必须是开启的(Required),否则获取不到        return sessionFactory.getCurrentSession();    }    @Override //保存    public long save(M model) {        return ((Long)this.getSession().save(model)).longValue();    }    @Override   //保存或者更新    public void saveOrUpdate(M model) {        this.getSession().saveOrUpdate(model);    }    @Override   //更新    public void update(M model) {        this.getSession().update(model);    }    //根据sql语句更新    public void updateBySQL(String sql, Object... params) {        Query query = getSession().createQuery(sql);        setParameters(query, params);        query.executeUpdate();    }    @Override   //按照主键删除    public void delete(long id) {        this.getSession().delete(id);    }    @Override   //按照对象删除    public void deleteObject(M model) {        this.getSession().delete(model);    }    @Override   //通过主键获得    public M get(long id) {        return (M) getSession().get(this.entityClass, id);    }    @Override      //根据主键判断是否存在    public boolean exists(long id) {        return this.get(id) != null;    }    @Override   //刷新    public void flush() {        getSession().flush();    }    @Override    //清理    public void clear() {        getSession().clear();    }    @Override   //获取所有挑数    public int countAll() {        return getSession().createQuery(HQL_COUNT_ALL).list().size();    }    @Override   //获取所有对象    public List<M> listAll() {        return getSession().createQuery(HQL_LIST_ALL).list();    }    @Override   //按照分页获取    public List<M> listAll(int start, int limit) {        return getSession().createQuery(HQL_LIST_ALL).setFirstResult(start).setMaxResults(limit).list();    }    //根据条件分页查询    public List<M> listAllByConditionsAndPaging(String sql, int start, int limit, Object... params) {        Session session = getSession();        Query query = session.createQuery(sql);        setParameters(query, params);        query.setFirstResult(start).setMaxResults(limit);        return query.list();    }    //根据条件不分页查询    public List<M> listAllByConditionsAndPaging(String sql, Object... params) {        Session session = getSession();        Query query = session.createQuery(sql);        setParameters(query, params);        return query.list();    }    //设置参数    protected void setParameters(Query query, Object[] paramlist) {        if (paramlist != null) {            for (int i = 0; i < paramlist.length; i++) {                if (paramlist[i] instanceof Date) {                    query.setTimestamp(i, (Date) paramlist[i]);                } else {                    query.setParameter(i, paramlist[i]);                }            }        }    }    /**     * 根据查询条件返回唯一一条记录     */    protected <T> T getUniqueResult(final String hql, final Object... paramlist) {        Query query = getSession().createQuery(hql);        setParameters(query, paramlist);        return (T) query.setMaxResults(1).uniqueResult();    }    /**     * 执行nativeSQL批处理语句.如 之间insert, update, delete 等.     */    protected int execteNativeSQLUpdate(final String natvieSQL, final Object... paramlist) {        Query query = getSession().createSQLQuery(natvieSQL);        setParameters(query, paramlist);        Object result = query.executeUpdate();        return result == null ? 0 : ((Integer) result).intValue();    }    protected List<Map<String, Object>> execteNativeSQLSelect(String natvieSQL, final Object... paramlist) {        SQLQuery query = getSession().createSQLQuery(natvieSQL);        setParameters(query, paramlist);        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);        return query.list();    }    protected List<Map<String, Object>> execteNativeSQLSelect(String natvieSQL, int start, int limit, Object... paramlist) {        SQLQuery query = getSession().createSQLQuery(natvieSQL);        setParameters(query, paramlist);        query.setFirstResult(start);        query.setMaxResults(limit);        query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);        return query.list();    }}

?再然后,看看具体的DAO,这里面有业务逻辑需要的独特的方法:CustomerDAO

package com.zq.demo.dao;import com.zq.common.dao.IBaseDAO;import com.zq.demo.po.Customer;import java.util.List;import java.util.Map;public interface CustomerDAO extends IBaseDAO<Customer> {    public List<Map<String,Object>> listAllAddrOfCustomer();}

?然后实际去干活的人出场喽:CustomerDAOImpl

package com.zq.demo.daoImpl;import com.zq.common.dao.hibernate.BaseHibernateDAO;import com.zq.demo.dao.CustomerDAO;import com.zq.demo.po.Customer;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import java.util.ArrayList;import java.util.List;import java.util.Map;@Component("customerDAO")public class CustomerDAOImpl extends BaseHibernateDAO<Customer> implements CustomerDAO {    @Autowired    @Qualifier("sessionFactory")    private SessionFactory sessionFactory;    @Override    public List<Map<String, Object>> listAllAddrOfCustomer() {        Session session=sessionFactory.getCurrentSession();        //do something        List<Map<String,Object>> list=new ArrayList<Map<String, Object>>();        return list;    }}

?以上只是简单的演示,里面有很多逻辑都是简化的不能再简化了。至于这四个DAO之间的关系,还是看着那个图理解比较好,一个图胜过一千行文字。再贴上一段简单的测试代码,保存一个customer:

@Test    public void testSave01() {        ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext_new.xml");        CustomerDAO customerDAO=(CustomerDAO)ac.getBean("customerDAO");        Customer customer = new Customer();        customer.setBirthday(new Date());        customer.setName("peterandy");        customer.setPwd("ssssss");        customerDAO.save(customer);    }

?发出的SQL语句如下:


struts2+spring3+hibernate4调整(3)-包的组织和DAO层的重构
?到此为止,DAO层的重构就已经完成,里面参考了大量的Zhang Kaitao老师的代码,感谢他的无私奉献。

? ? ? ? 剩下的工作还有:

? ? ? ? 一、继续完善DAO层,增加对异常的处理等。

? ? ? ? 二、思考如何完成动态查询,即查询条件数量不定的查询。我先简单描述一下这个问题,请教一下大家:比如页面上有10个可供查询的条件,但是用户需要的数量是不确定的,可能有的用户只需要2个,有的可能得需要8个,这样一来,用不到的查询条件就得在输出的sql里转化成1=1才能保证程序的正确性。可是这个怎么具体实现呢,简单地拼接SQL字符串就怕被SQL注入,这个地方是我下面要继续完善的地方。

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?
谢谢 有什么不对的地方还望指出哈,嘿嘿 好 好
呵呵,还望多多指教啊! ,稍后整理一下源码就上传。 我再改进一下。 ,抽空再继续优化一下,供大家分享。 谢谢指正for (int i = 0; i < paramlist.length; i++) { 可改为
for (int i = 0,length=paramList.length; i < length; i++) {  
for (int i = 0; i < paramlist.length; i++) { 可改为
for (int i = 0,length=paramList.length; i < length; i++) {  

嗯嗯,谢谢指正 可以直接调用父类的getSession获取session。关于那个循环确实有点草率了,以前就吃过这样的亏,谢谢你又提醒了我~~

热点排行