持久层之DAO

本文详细介绍了DAO(数据访问对象)的设计理念与实现细节,包括其核心功能——增删查改及连接管理,并提供了具体的接口定义与实现类示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

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

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


UML

153208_fcXh_1027544.png



代码示例

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为核心,其他的无非是连接池的运用,各种工厂类的运用(即设计模式的运用)…………等等。

转载于:https://my.oschina.net/diedai/blog/533085

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值