数据库框架设计与实现(一)

一、设计目标

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的支持,今后我仍会逐步完善(本篇文章会同步更新),后续文章中也会出现连载。

这里也可以看做是给大家一个思路,如果各位有好的想法和建议,清多多留言交流!

你可能感兴趣的:(java,spring,hibernate,项目经验)