一、设计目标
1. 对上层提供统一、唯一的接口,不仅支持关系型数据库,还要支持非关系型数据库。
2. 以基于ORM思想,泛型为实现的方法进行数据库操作进行封装。
3. 实现数据库可配置,可替换。
二、框架图
框架核心采用了工厂模式+简单工厂模式,本来应该由BaseDao去实现Query来构成工厂模式,但为了最大程度解耦,在创建Query时又采用了简单工厂去关联IQuery接口。UserDao则是客户端调用者,同样采用简单工厂来与IDataBaseDao关联。IPageModel、ITreeModel则分别是为分页、树形结构服务的。(这里一说到简单工厂,实际上是交由spring的IOC来完成的)最终使得任何类都是基于接口实现,从而达到整体框架灵活性。
三、代码实现
1. IDataBaseDao
package com.core.dao; import java.io.Serializable; import java.util.Collection; import java.util.List; /** * 数据库访问操作对象 * @author Wang * @param <T> 实体类 * @param <PK> 主键类型 */ public interface IDataBaseDao<T extends Serializable, PK extends Serializable> { /** * 设置实体类 * @param entityClass 实体类class */ void setEntityClass(Class<T> entityClass); /** * 新建一个查询对象 * @return */ IQuery createQuery(); /** * 获取数据 * @param id 主键 * @return */ T get(PK id); /** * 加载数据 * @param id 主键 * @return */ T load(PK id); /** * 加载全部数据 * @return */ List<T> loadAll(); /** * 查询数据 * @param query 查询对象 * @return */ List<T> find(IQuery query); /** * 保存数据 * @param entity 实体类 * @return */ PK save(T entity); /** * 更新数据 * @param entity 实体类 */ void update(T entity); /** * 保存或更新数据 * @param entity 实体类 */ void saveOrUpdate(T entity); /** * 保存或更新全部数据 * @param entities 实体类集合 */ void saveOrUpdateAll(Collection<T> entities); /** * 删除数据 * @param entity 实体类 */ void delete(T entity); /** * 依据主键删除数据 * @param id 主键 */ void deleteByKey(PK id); /** * 删除全部数据 * @param entities 实体类集合 */ void deleteAll(Collection<T> entities); }
说明:
该接口是本系统数据库框架对外提供服务的核心接口,也是各个数据库实现框架(hibernate、ibatis、)的抽象接口,使本系统不局限于某种数据库实现框架,支持各种常见数据库实现框架。
系统其它框架都要统一调用接口,不可直接调用实现类。
支持泛型。第一个T为返回对象类型,第二个PK为主键类型。
2. IQuery
package com.core.dao; import java.util.List; /** * 查询操作对象 * @author Wang */ public interface IQuery { /** * 获取对象查询语句 * @return */ String getQueryString(); /** * 获取sql查询语句 * @return */ String getSQLString(); /** * 获取查询参数集合 * @return */ Object[] getParamValues(); /** * 获取查询数据的起始位号,用于分页 * @return */ int getFirstResult(); /** * 获取查询数据的最大长度,用于分页 * @return */ int getMaxResults(); /** * 设置表的实体类集合 * @param entityClasses 实体类class集合 */ @SuppressWarnings("rawtypes") void setEntityClass(Class[] entityClasses); /** * 设置对象查询语句 * @param queryStr 对象查询语句字符串 */ void setQueryString(String queryStr); /** * 设置sql查询语句 * @param sql sql查询语句字符串 */ void setSQLString(String sql); /** * 设置查询参数集合 * @param values 参数值集合 */ void setParamValues(Object[] values); /** * 设置查询数据的起始值,用于分页 * @param value 起始值 */ void setFirstResult(int value); /** * 设置查询数据的最大长度,用于分页 * @param value 最大值 */ void setMaxResults(int value); /** * 执行查询 * @return */ @SuppressWarnings("rawtypes") List execute(); }
说明:
该接口是专门针对于查询数据库设计的,不同数据库,其查询语言都不太一样,而增删改操作则都较为简单。任何涉及到查询数据库的操作都要统一采用此接口的方式实现。
提供对原生SQL的支持,即getSQLString、setSQLString,同时该方法并不仅仅用于SQL语句,同样适用于非关系数据库的一些特殊的查询语句(如Mongodb),而getQueryString、setQueryString则是针对面向对象的查询语句而独自提供的方法。
为了防止一些查询语句无法彻底封装,提供了一个excute方法来完成查询。
提供getFirstResult等方法来对分页查询提供支持。
3. IPageModel
package com.core.dao; import java.io.Serializable; import java.util.List; /** * 分页操作对象 * @author Wang * @param <T> 数据对象类型 */ public interface IPageModel<T extends Serializable> { /** * 获取一页显示多少条数据的值 * @return */ int getPageSize(); /** * 获取总页数的值 * @return */ int getTotalPages(); /** * 获取当前页号 * @return */ int getPageNumber(); /** * 获取该页第一条数据的行号 * @return */ int getFirstResult(); /** * 获取该页数据 * @return */ List<T> getDataResult(); /** * 是否是首页 * @return */ boolean isFirstPage(); /** * 是否是尾页 * @return */ boolean isLastPage(); /** * 设置一页显示多少条数据 * @param value */ void setPageSize(int value); /** * 设置总页数 * @param value */ void setTotalPages(int value); /** * 设置当前页号 * @param value */ void setPageNumber(int value); /** * 设置该页第一条数据的行号 * @param value */ void setFirstResult(int value); /** * 设置该页数据 * @param data */ void setDataResult(List<T> data); }
说明:
该接口用于分页功能,任何分页的实现都必须用该接口。
4. ITreeModel
package com.core.dao; import java.io.Serializable; public interface ITreeModel<PK extends Serializable> { PK getNodeId(); PK getNodePid(); String getNodeName(); int getNodeOrder(); String getNodeImage(); int getNodeLevel(); void setNodeId(PK nodeId); void setNodePid(PK nodePid); void setNodeName(String nodeName); void setNodeOrder(PK nodeOrder); void setNodeImage(String nodeImage); void setNodeLevel(int nodelLevel); }
说明:
该接口用于树形功能。任何树形的实现都必须用该接口。
5. BaseDao
package com.core.dao.hibernate; import java.io.Serializable; import java.sql.SQLException; import java.util.Collection; import java.util.List; import javax.annotation.Resource; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.HibernateTemplate; import com.core.dao.IDataBaseDao; import com.core.dao.IQuery; import com.util.BeanUtil; public class BaseDao<T extends Serializable, PK extends Serializable> implements IDataBaseDao<T, PK> { @Resource private HibernateTemplate hibernateTemplate; @Resource private IQuery query; private Class<T> entityClass; @Override public void setEntityClass(Class<T> entityClass) { this.entityClass = entityClass; } @Override public IQuery createQuery() { return query; } @SuppressWarnings("unchecked") @Override public T get(PK id) { return (T) hibernateTemplate.get(entityClass, id); } @SuppressWarnings("unchecked") @Override public T load(PK id) { return (T) hibernateTemplate.load(entityClass, id); } @SuppressWarnings("unchecked") @Override public List<T> loadAll() { return hibernateTemplate.loadAll(entityClass); } @SuppressWarnings("unchecked") @Override public List<T> find(IQuery query) { final String queryString = query.getQueryString(); if (!BeanUtil.isNull(queryString)) { final Object[] values = query.getParamValues(); final int firstResult = query.getFirstResult(); final int maxResult = query.getMaxResults(); if (!BeanUtil.isNull(values)) { if (maxResult > 0) { hibernateTemplate.executeFind(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery(queryString); query.setFirstResult(firstResult); query.setMaxResults(maxResult); for (int i = 0; i < values.length; i++) { query.setParameter(i + 1, values[i]); } return query.list(); } }); } return hibernateTemplate.find(queryString, values); } else { if (maxResult > 0) { hibernateTemplate.executeFind(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery(queryString); query.setFirstResult(firstResult); query.setMaxResults(maxResult); return query.list(); } }); } return hibernateTemplate.find(queryString); } } String sql = query.getSQLString(); if (!BeanUtil.isNull(sql)) { return query.execute(); } else { // //////////// 需要抛出异常 return null; } } @SuppressWarnings("unchecked") @Override public PK save(T entity) { return (PK) hibernateTemplate.save(entity); } @Override public void update(T entity) { hibernateTemplate.update(entity); } @Override public void saveOrUpdate(T entity) { hibernateTemplate.saveOrUpdate(entity); } @Override public void saveOrUpdateAll(Collection<T> entities) { hibernateTemplate.saveOrUpdateAll(entities); } @Override public void delete(T entity) { hibernateTemplate.delete(entity); } @Override public void deleteByKey(PK id) { T t = this.get(id); hibernateTemplate.delete(t); } @Override public void deleteAll(Collection<T> entities) { hibernateTemplate.deleteAll(entities); } }
说明:
该类是对IDataBaseDao的实现,也是基于Hibernate框架的实现类。
6. Query
package com.core.dao.hibernate; import java.util.List; import com.core.dao.IQuery; public class Query implements IQuery { private String queryStr; private String sql; private Object[] params; private int firstResult; private int maxResult; @SuppressWarnings({ "rawtypes", "unused" }) private Class[] entityClasses; @Override public String getQueryString() { return queryStr; } @Override public String getSQLString() { return sql; } @Override public Object[] getParamValues() { return params; } @Override public int getFirstResult() { return firstResult; } @Override public int getMaxResults() { return maxResult; } @SuppressWarnings("rawtypes") @Override public void setEntityClass(Class[] entityClasses) { this.entityClasses = entityClasses; } @Override public void setQueryString(String queryStr) { this.queryStr = queryStr; } @Override public void setSQLString(String sql) { this.sql = sql; } @Override public void setParamValues(Object[] values) { this.params = values; } @Override public void setFirstResult(int value) { this.firstResult = value; } @Override public void setMaxResults(int value) { this.maxResult = value; } @SuppressWarnings("rawtypes") @Override public List execute() { return null; } }
该类是对IQuery的实现,也是基于Hibernate框架的实现类。
6. applicationContext.xml(部分,其他的自己配)
<bean id="baseDao" class="com.core.dao.hibernate.BaseDao"></bean> <bean id="query" class="com.core.dao.hibernate.Query" scope="prototype"></bean> <bean name="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory" /> </bean>
四、结语
目前这个框架还处于初期阶段,只实现了对Hibernate的支持,今后我仍会逐步完善(本篇文章会同步更新),后续文章中也会出现连载。
这里也可以看做是给大家一个思路,如果各位有好的想法和建议,清多多留言交流!