文档章节

持久层之DAO

对岸
 对岸
发布于 2015/11/20 10:48
字数 2016
阅读 316
收藏 1

前言

DAO的意思是数据访问对象,就是用该类来访问数据库,具体来说是执行增删查改的。

另外,还需要负责获取连接对象和关闭连接对象。


UML



代码示例

1、接口

1)增删查改。

2)获取连接对象和关闭连接对象。

package com.bigning.db;

import java.io.*;
import java.util.*;
import java.util.Date;
import java.sql.*;

import com.bigning.Important;
import com.bigning.ImportantLevel;

/**
 * DAO接口
 * 
 * @author gzh
 * @see AbstractDal
 * 
 */
@Important(ImportantLevel.Top)
public interface ComDal extends Serializable {
	/**
	 * 增、删、改
	 * 
	 * @param sql
	 *            sql语句
	 * @return 记录数量
	 * @throws DalException
	 */
	public int execCommand(String sql) throws DalException;

	/**
	 * 增、删、改
	 * 
	 * @param sql
	 *            sql语句
	 * @param date
	 *            日期
	 * @return 记录数量
	 * @throws DalException
	 */
	public int execCommand(String sql, java.util.Date date) throws DalException;

	/**
	 * 增、删、改
	 * 
	 * @param sql
	 *            sql语句
	 * @param dates
	 *            日期数组
	 * @return 记录数量
	 * @throws DalException
	 */
	public int execCommand(String sql, java.util.Date[] dates)
			throws DalException;

	/**
	 * 增、删、改
	 * 
	 * @param sql
	 *            sql语句
	 * @param dates
	 *            日期列表
	 * @return 记录数量
	 * @throws DalException
	 */
	public int execCommand(String sql, List<Date> dates) throws DalException;

	/**
	 * 查询
	 * 
	 * @param sql语句
	 * @return 结果集
	 * @throws DalException
	 */
	public ResultSet doSelect(String sql) throws DalException;

	/**
	 * 查询
	 * 
	 * @param sql
	 *            sql语句
	 * @param date
	 *            日期
	 * @return 结果集
	 * @throws DalException
	 */
	public ResultSet doSelect(String sql, java.util.Date date)
			throws DalException;

	/**
	 * 查询
	 * 
	 * @param sql
	 *            sql语句
	 * @param dates
	 *            日期数组
	 * @return 结果集
	 * @throws DalException
	 */
	public ResultSet doSelect(String sql, java.util.Date[] dates)
			throws DalException;

	/**
	 * 查询
	 * 
	 * @param sql
	 *            sql语句
	 * @param dates
	 *            日期列表
	 * @return 记录集
	 * @throws DalException
	 */
	public ResultSet doSelect(String sql, List<Date> dates) throws DalException;

	/**
	 * 执行一批命令
	 * 
	 * @param arrSqls
	 *            命令数组
	 */
	public void execBatch(String[] arrSqls) throws DalException;

	/**
	 * 执行一组命令
	 */
	public void execBatch(List<String> vSqls) throws DalException;

	/**
	 * 执行存储过程(对 SQL Server而言)
	 * 
	 * @param spName
	 *            存储过程名称
	 * @param spParams
	 *            存储过程的参数
	 */
	public void execStoreCommand(String spName, String spParams)
			throws DalException;

	/**
	 * 取得连接对象
	 * 
	 * @return 连接对象
	 */
	public Connection getConnection() throws DalException;

	/**
	 * 清除历史的 statment
	 */
	public void clearHistory();

	/**
	 * 关闭结果集对象、语句对象和连接对象
	 */
	public void closeConnection();

	/**
	 * 取得最后执行的一条 SQL 语句
	 */
	public String getLastSql();

	/**
	 * 取得连接生成器
	 */
	public ConnectionGenerator getConnectionGenerator();

	/**
	 * 设置数据的 Filter,插入到数据库之前, 将数据进行 convert 一下 -- updated on 20030117
	 */
	// public void setFilter(DataFilter df);
	/**
	 * 移除过滤器 -- updated on 20030117
	 */
	// public DataFilter removeFilter() ;
	
	/**
	 * 设置要获取的记录数量
	 * @param fetchSize 记录数量
	 */
	public void setFetchSize(int fetchSize);
};



2、实现类(非连接池)

注:该类是DAO接口的实现类,并不是抽象类,这里命名错误!

package com.bigning.db;

import java.util.*;
import java.util.Date;
import java.sql.*;
import org.apache.log4j.*;

import com.bigning.Important;
import com.bigning.ImportantLevel;

/**
 * DAO的实现类: 作为一个基本的 DAL 类存在, 而并不是一个Abstract 类, 可作为 ComDal 的一个参考实现
 * 
 * @author Administrator
 * 
 */
@Important(ImportantLevel.Top)
public class AbstractDal implements ComDal, Cloneable {
	/**
	 * Comment for <code>serialVersionUID</code>
	 */
	private static final long serialVersionUID = 3257001055735658040L;

	static PreProcesser SPP = new PreProcesser();
	// 字段定义
	private ConnectionGenerator cg; // 连接生成器
	private String lastSql; // 最后执行的 SQL 语句
	protected Connection conn; // 数据库连接
	private LinkedList<Statement> historyStatements;
	private LinkedList<ResultSet> historyResultSets;
	private static final Logger logger = Logger.getLogger(AbstractDal.class);
	// private DataFilter filter;
	int fetchSize = 20;

	// 构造方法说明:
	/**
	 * @param cg
	 *            连接生成器
	 */
	public AbstractDal(ConnectionGenerator cg) {
		this.cg = cg;
		historyStatements = new LinkedList<Statement>();
		historyResultSets = new LinkedList<ResultSet>();
	}

	// 其他方法说明:
	/**
	 * 执行 SQL 命令, 如 Insert, Delete等
	 * 
	 * @param sql
	 *            SQL命令
	 * @throws DalException
	 *             封装SQL语句出错的命令
	 */
	public int execCommand(String sql) throws DalException {
		return execCommand(sql, SPP);
	}

	/**
	 * 执行 SQL 命令, 如 Insert, Delete等
	 * 
	 * @param sql
	 *            SQL命令
	 * @param aDate
	 *            一个日期
	 */
	public int execCommand(String sql, java.util.Date aDate)
			throws DalException {
		return execCommand(sql, new DatePreProcesser(aDate));
	}

	/**
	 * 执行 SQL 命令,如 Insert, Delete等, 但这条命令中包括有 Date 类型需要设置
	 * 
	 * @param sql
	 *            SQL 命令
	 * @param dates
	 *            一组日期
	 */
	public int execCommand(String sql, java.util.Date[] dates)
			throws DalException {
		return execCommand(sql, new DatePreProcesser(dates));

	}

	/**
	 * 执行 SQL 命令,如 Insert, Delete等, 但这条命令中包括有 Date 类型需要设置
	 * 
	 * @param sql
	 *            SQL 命令
	 * @param dates
	 *            一组日期
	 */
	public int execCommand(String sql, List<Date> dates) throws DalException {
		return execCommand(sql, new DatePreProcesser(dates));
	}

	private int execCommand(String sql, PreProcesser dpp) throws DalException {
		ensureConnected();
		lastSql = sql;
		int r = 0;
		try {
			PreparedStatement ps = conn.prepareStatement(sql);
			try {
				dpp.process(ps);
				r = ps.executeUpdate();
			} finally {
				ps.close();
			}
			logSucc(sql);
		} catch (SQLException ex) {
			logFail(ex, sql + dpp.getDates());
			throw new DalException(this, ex, sql + dpp.getDates());
		}
		return r;
	}

	/**
	 * 执行 SQL 查询命令
	 * 
	 * @param sql
	 *            SQL查询语句
	 * @return 记录集
	 */
	/**
	 * 执行一批命令
	 * 
	 * @param arrSqls
	 *            命令数组
	 */
	public void execBatch(String[] arrSqls) throws DalException {
		ensureConnected();
		try {
			Statement s = conn.createStatement();
			try {
				for (int i = 0; i < arrSqls.length; i++) {
					lastSql = arrSqls[i];
					s.executeUpdate(lastSql);
					logSucc(lastSql);
				}
			} finally {
				s.close();
			}
		} catch (SQLException ex) {
			logFail(ex, lastSql);
			throw new DalException(this, ex, lastSql);
		} // end of catch
	}

	/**
	 * 执行一组命令
	 */
	public void execBatch(List<String> vSqls) throws DalException {
		String[] s = new String[vSqls.size()];
		vSqls.toArray(s);
		execBatch(s);
	}

	/**
	 * 执行 SQL 查询命令
	 * 
	 * @param sql
	 *            SQL查询语句
	 * @return 结果集
	 */
	public ResultSet doSelect(String sql) throws DalException {
		return doSelect(sql, SPP);
	}

	/**
	 * 执行查询语句
	 * 
	 * @param sql
	 *            sql语句
	 * @param spp
	 *            预处理
	 * @return 结果集
	 * @throws DalException
	 */
	private ResultSet doSelect(String sql, PreProcesser spp)
			throws DalException {
		ensureConnected();
		lastSql = sql;
		try {
			PreparedStatement s = conn.prepareStatement(sql,
					ResultSet.TYPE_SCROLL_INSENSITIVE,
					ResultSet.CONCUR_READ_ONLY);
			try {
				s.setFetchSize(fetchSize);
			} catch (Exception ex) {
			}
			spp.process(s);
			ResultSet r = s.executeQuery();
			try {
				r.setFetchSize(fetchSize);
			} catch (Exception ex) {
			}
			synchronized (historyStatements) {
				historyStatements.addLast(s);
				historyResultSets.addLast(r);
			}
			logSucc(sql);
			return r;
		} catch (SQLException ex) {
			logFail(ex, sql + spp.getDates());
			throw new DalException(this, ex, sql + spp.getDates());
		} // end of catch
	}

	/**
	 * 执行 SQL 查询命令
	 * 
	 * @param sql
	 *            SQL查询语句
	 * @return 结果集
	 */
	public ResultSet doSelect(String sql, Date aDate) throws DalException {
		return doSelect(sql, new DatePreProcesser(aDate));
	}

	/**
	 * 执行 SQL 查询命令
	 * 
	 * @param sql
	 *            SQL查询语句
	 * @param dates
	 *            一组日期
	 * @return 记录集
	 */
	public ResultSet doSelect(String sql, Date[] dates) throws DalException {
		return doSelect(sql, new DatePreProcesser(dates));
	}

	/**
	 * 执行 SQL 查询命令
	 * 
	 * @param sql
	 *            SQL查询语句
	 * @param dates
	 *            一组日期
	 * @return 记录集
	 */
	public ResultSet doSelect(String sql, List<Date> dates) throws DalException {
		return doSelect(sql, new DatePreProcesser(dates));
	}

	/**
	 * 执行一批命令
	 * 
	 * @param arrSqls
	 *            命令数组
	 */
	/**
	 * 清除历史记录的Statement
	 */
	public void clearHistory() {
		synchronized (historyStatements) {
			for (ResultSet rs : historyResultSets) {
				try {
					rs.close();
				} catch (Exception ex) {
				}
			}
			historyResultSets.clear();

			for (Statement s : historyStatements) {
				try {
					s.close();
				} catch (Exception ex) {
				}
			}
			historyStatements.clear();
		}
	}

	/**
	 * 执行存储过程(对 SQL Server而言)(未实现)
	 * 
	 * @param spName
	 *            存储过程名称
	 * @param spParams
	 *            存储过程的参数
	 */
	public void execStoreCommand(String spName, String spParams)
			throws DalException {
		throw new DalException(" store Command is not supported by "
				+ getClass().getName());
	}

	/**
	 * 取得连接对象
	 * 
	 * @return 连接对象
	 */
	public Connection getConnection() throws DalException {
		ensureConnected();
		return conn;
	}

	/**
	 * 关闭连接串
	 */
	public void closeConnection() {
		clearHistory();
		try { // an exception would be shrown here, I try to catch it!
			if (conn != null) { // start of if
				doCloseConnection(conn);
			} // end of if
		} catch (Exception ex) { //
			// ex.printStackTrace(); // Print Stack Trace
		} // end of catch
		finally {
			conn = null;
		}
	}

	protected void doCloseConnection(Connection c) throws SQLException {
		c.close();
	}

	/**
	 * 取得最后执行的一条 SQL 语句
	 * 
	 * @return 通过 DAL 执行的最后一条 SQL 语句
	 */
	public String getLastSql() {
		return lastSql;
	}

	/**
	 * 确保当前有连接对象:如果没有的话,创建一个连接对象
	 * 
	 * @throws DalException
	 */
	private void ensureConnected() throws DalException {
		try {
			if (conn == null || conn.isClosed()) { // 如果当前没有连接对象,那么创建连接对象
				conn = openConnection();
			} // end of if
		} catch (SQLException ex) {
			throw new DalException(this, ex, "Fail to Connect To Database");
		} // end of catch
	}

	/**
	 * 获取连接对象
	 * 
	 * @return
	 * @throws ConnectFailException
	 */
	protected Connection openConnection() throws ConnectFailException {
		return cg.getConnection();
	}

	public void finalize() {
		closeConnection();
	}

	/**
	 * 取得连接生成器
	 */
	public ConnectionGenerator getConnectionGenerator() {
		return cg;
	}

	private void doLog(Throwable t, String msg) {
		logger.error(msg, t);

	}

	private void logSucc(String sql) {
		logger.info(sql + "? SUCCESS");
	}

	private void logFail(Throwable t, String sql) {
		doLog(t, sql + "? FAILUER");
	}

	public String toString() {
		return "AbstractDal\r\nConnectionString: " + cg.getConnString()
				+ "\r\nLast SQL: " + lastSql;
	}

	public Object clone() {
		try {
			AbstractDal dal = (AbstractDal) super.clone();
			dal.conn = null;
			dal.historyResultSets = new LinkedList<ResultSet>();
			dal.historyStatements = new LinkedList<Statement>();
			return dal;
		} catch (Exception ex) {
			// ex.printStackTrace();
			logger.error("Cannot Clone the Dal", ex);
		}
		return new AbstractDal(this.cg);
	}

	public void setFetchSize(int fetchSize) {
		if (fetchSize < 1) {
			fetchSize = 20; //如果要获取的记录数量小于1,那么默认设置为20
		}
		
		this.fetchSize = fetchSize;
	}
}


3、DAO实现类(连接池)

/*
 * @(#)
 *
 * Copyright bigNing(javaning@sina.com, 2003.06.01
 */
package com.bigning.db.pool;

import java.sql.Connection;
import java.sql.SQLException;


import com.bigning.db.*;

/**
* 可缓冲的数据访问层
*/
public class  PoolableComDal extends AbstractDal implements ComDal {
	/**
	 * Comment for <code>serialVersionUID</code>
	 */
	private static final long serialVersionUID = 3546923576121899056L;

	/**
	 * 默认的连接关闭监听器
	 * 关闭连接 -- 非缓冲 
	 * @author fantasy
	 *
	 */
	private static class CloseConnReleaseListener implements ConnReleaseListener{

		/* (non-Javadoc)
		 * @see bigning.db.pool.ConnReleaseListener#connReleased(bigning.db.pool.ConnReleaseEvent)
		 */
		public void connReleased(ConnReleaseEvent cre) {
			Connection c=cre.getConnection();
			try{
				c.close();
			}
			catch (Throwable e ){}
		}
		
	}
	//默认的连接关闭监听器
	private static final ConnReleaseListener DEFAULT_LISTENER=new CloseConnReleaseListener();
	// 连接关闭监听器
	private ConnReleaseListener listener;
	/**
	 * 构造缓冲的数据访问层
	 * @param cg 连接生成器
	 * @param lsnr 连接关闭监听器
	 */
	public PoolableComDal(PoolableConnectionGenerator cg,ConnReleaseListener lsnr) {
		super(cg);
		if(lsnr==null){
			lsnr=DEFAULT_LISTENER;
		}
		listener=lsnr;
	}
	/**
	 * 构造普通的数据访问层
	 * @param cg 连接生成器
	 */
	public PoolableComDal(PoolableConnectionGenerator cg) {
		this(cg,DEFAULT_LISTENER);
	}
	public void setConnReleaseListener(ConnReleaseListener listener) {
		if(listener==null){
			listener=DEFAULT_LISTENER;
		}
		this.listener=listener;
	}
	/**
	 * 移除连接关闭监听器, 并使用默认监听器
	 * @return 当前使用的监听器
	 */
	public ConnReleaseListener removeConnReleaseListener() {
		ConnReleaseListener l=listener;
		listener=DEFAULT_LISTENER;
		return l;
	}

	/**
	 * 关闭连接串
	 * @throws SQLException
	 */
	protected  void doCloseConnection(Connection c) throws SQLException{
		listener.connReleased(new ConnReleaseEvent(this,c));
	}

}


总结

所有的关于持久层的实现或者说思想原理什么的,都是围绕着DAO的2大功能(即增删查改功能和获取/关闭连接对象)来实现的。


以DAO为核心,其他的无非是连接池的运用,各种工厂类的运用(即设计模式的运用)…………等等。

© 著作权归作者所有

下一篇: jforum 分页功能
对岸
粉丝 4
博文 96
码字总数 24981
作品 0
私信 提问
说说 Spring DAO 的设计思想

DAO (Data Access Object )是访问数据的对象,它不但屏蔽了不同的数据存储介质(数据库、文件或 LDAP 等),也屏蔽了具体的实现技术 。 我们只要为数据访问定义好 DAO 接口,然后使用具体技...

deniro
2018/09/23
0
0
SRP和LSP在架构中的具体应用

在ssh构架的后台应用中,我们将应用分为model层,service层,dao层,这是一个SRP原则的具体实现,每一个层的职责单一化,逻辑更清晰,层与层之间分开,类与类之间耦合度低,功能的复用性得到...

山如
2018/09/11
0
0
图解JavaWeb开发模式及MVC

疑问区? 1.在JavaWeb开发中将MVC与业务层、持久层、表现层相结合的运用有何好处? 用三层架构可以降低层与层之间的耦合度。 2.Servlet是如何是如何调用业务层的呢?(说明过程) 通过接口一...

鲁雯雪
2013/11/08
1K
2
java领域模型中的失血、贫血、充血、胀血模型

为了补大家的遗憾,在此总结下ROBBIN的领域模型的一些观点和大家的补充,在网站和演讲中,robbin将领域模型初步分为4大类: 1,失血模型 2,贫血模型 3,充血模型 4,胀血模型 那么让我们看看...

萧萧恋
2013/07/15
612
1
【转贴】贫血,充血模型的解释以及一些经验(非常经典)

领域模型分为4大类: 1,失血模型 2,贫血模型 3,充血模型 4,胀血模型 那么让我们看看究竟有这些领域模型的具体内容,以及他们的优缺点: 一、失血模型 失血模型简单来说,就是domain obje...

鉴客
2010/08/11
7.6K
8

没有更多内容

加载失败,请刷新页面

加载更多

学习记录 java面试题(一)

1. JDK和JRE的区别 JDK是整个JAVA的核心,包括了Java运行环境JRE,一堆Java工具和Java基础的类库。通过JDK开发人员将源码 文件(java文件)编译成字节码文件(class文件)。 JRE是Java运行环境,...

Pole丶逐
25分钟前
5
0
springboot 部署到外部tomcat

入口类继承SpringBootServletInitializer 并重写protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)方法 如下 import org.springframework.boot.SpringApplic......

雷开你的门
31分钟前
4
0
hashCode和equals方法的关系

equals相等,hashcode必相等; hashCode()在哈希表中起作用,如HashSet、HashMap等。 当我们向哈希表(如HashSet、HashMap等)中添加对象object时,首先调用hashCode()方法计算object的哈希码,...

无名氏的程序员
35分钟前
2
0
技术分享 | MySQL 慢查询记录原理和内容解析

作者:高鹏 文章末尾有他著作的《深入理解 MySQL 主从原理 32 讲》,深入透彻理解 MySQL 主从,GTID 相关技术知识。 源码版本:percona 5.7.14 本文为学习记录,可能有误请谅解,也提供了一些...

爱可生
44分钟前
3
0
elementui 树型节点

节点选择时,勾选节点。 提交给后端时,传递 this.$refs.menuTree.getCheckedKeys(); 半选父节点 getHalfCheckedKeys() 不需要提交。...

东东笔记
44分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部