一、设计目标
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 实体类
* @param 主键类型
*/
public interface IDataBaseDao {
/**
* 设置实体类
* @param entityClass 实体类class
*/
void setEntityClass(Class entityClass);
/**
* 新建一个查询对象
* @return
*/
IQuery createQuery();
/**
* 获取数据
* @param id 主键
* @return
*/
T get(PK id);
/**
* 加载数据
* @param id 主键
* @return
*/
T load(PK id);
/**
* 加载全部数据
* @return
*/
List loadAll();
/**
* 查询数据
* @param query 查询对象
* @return
*/
List 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 entities);
/**
* 删除数据
* @param entity 实体类
*/
void delete(T entity);
/**
* 依据主键删除数据
* @param id 主键
*/
void deleteByKey(PK id);
/**
* 删除全部数据
* @param entities 实体类集合
*/
void deleteAll(Collection 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 数据对象类型
*/
public interface IPageModel {
/**
* 获取一页显示多少条数据的值
* @return
*/
int getPageSize();
/**
* 获取总页数的值
* @return
*/
int getTotalPages();
/**
* 获取当前页号
* @return
*/
int getPageNumber();
/**
* 获取该页第一条数据的行号
* @return
*/
int getFirstResult();
/**
* 获取该页数据
* @return
*/
List 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 data);
}
说明:
该接口用于分页功能,任何分页的实现都必须用该接口。
4. ITreeModel
package com.core.dao;
import java.io.Serializable;
public interface ITreeModel {
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 implements IDataBaseDao {
@Resource
private HibernateTemplate hibernateTemplate;
@Resource
private IQuery query;
private Class entityClass;
@Override
public void setEntityClass(Class 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 loadAll() {
return hibernateTemplate.loadAll(entityClass);
}
@SuppressWarnings("unchecked")
@Override
public List 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 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 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(部分,其他的自己配)
四、结语
目前这个框架还处于初期阶段,只实现了对Hibernate的支持,今后我仍会逐步完善(本篇文章会同步更新),后续文章中也会出现连载。
这里也可以看做是给大家一个思路,如果各位有好的想法和建议,清多多留言交流!