package com.dbtemplate.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import com.dbtemplate.domain.DataExchange;

/** *//**
* <pre>
* 抽象DAO类,提供了对数据库操作的封装,功能如下:
*
* ·连接获取和返回:使用数据源提供的连接池功能
* ·执行查询操作:返回ResultSet
* ·执行更新操作:执行插入、修改、删除操作
* ·返回当前页数据:返回用户当前查询的页面数据
*
* 其中的更新操作方法:insert(Object)、update(Object)、
* delete(Object)为抽象方法,由其子类实现继承。
* </pre>
*
* @author peng
*
*/
public abstract class AbstractDao ...{
static final String JDNI_NAME = "java:comp/env/jdbc/dbtemplate";
static Logger logger = Logger.getLogger(AbstractDao.class.getName());
static DataSource ds = null;
Connection con = null;
PreparedStatement pstm = null;
ResultSet rs = null;
// 初始化时获取数据源
static ...{
try ...{
// 从数据源中获取连接
Context ctx = new InitialContext();
ds = (DataSource) ctx.lookup(JDNI_NAME);
} catch (NamingException ne) ...{
logger.error("Error occured when get DataSource.");
ne.printStackTrace();
}
}

/** *//**
* <pre>
* 从数据源中获取数据库连接,注意如果是由于JNDI引起的异常,则
* 不向外抛出,而是直接打印异常信息。如果是SQL异常,则向上层
* 抛出。
* </pre>
*
* @throws SQLException:SQL异常
*/
private void createConnection() throws SQLException ...{
logger.debug("Start to get connection.");
try ...{
con = ds.getConnection();
} catch (SQLException sqle) ...{
logger.error("Error occured when get connection.");
throw sqle;
}
}

/** *//**
* 创建预编译语句
*
* @param sql:预编译语句的模版
* @throws SQLException:SQL异常
*/
private void createPreparedStatement(String sql) throws SQLException ...{
logger.debug("Start to create PreparedStatement.");
try ...{
pstm = con.prepareStatement(sql);
} catch (SQLException sqle) ...{
logger.error("Error occured when create PreparedStatement.");
throw sqle;
}
}

/** *//**
* <pre>
* 为预编译语句设置参数。注意此处使用的是setObject(int,Object)的方法,
* 是否正确尚需代测试检验。
* </pre>
*
* @param params:参数数组
* @throws SQLException:SQL异常
*/
private void setParametes(Object[] params) throws SQLException ...{
logger.debug("Start to set parameters.");
try ...{
// 循环设置预编译语句的参数
for (int i = 0; i < params.length; i++) ...{
pstm.setObject(i + 1, params[i]);
}
} catch (SQLException sqle) ...{
logger.error("Error occured when set parameters.");
throw sqle;
}
}

/** *//**
* <pre>
* 执行SQL查询,无参数
* </pre>
*
* @param sql:要执行代SQL查询语句
* @return java.sql.ResultSet
* @throws SQLException:SQL异常
*/
public synchronized ResultSet query(String sql) throws SQLException ...{
return query(sql, null);
}

/** *//**
* <pre>
* 执行SQL查询,使用指定的参数。Object数组中的每个元素将依次替换
* 到预编译语句的?处,返回结果是一个ReslutSet对象。
* </pre>
*
* @param sql:要执行的SQL查询语句
* @param params:预编译语句的参数数组
* @return java.sql.ResultSet
* @throws SQLException:SQL异常
*/
public synchronized ResultSet query(String sql, Object[] params) throws SQLException ...{
logger.debug("Start to execute query.");
try ...{
// 如果数据库连接为空,则先创建数据库连接
if (con == null) ...{
createConnection();
}
// 创建预编译语句
createPreparedStatement(sql);
// 为预编译语句设置参数
if (params != null) ...{
setParametes(params);
}
// 执行查询
rs = pstm.executeQuery();
} catch (SQLException sqle) ...{
logger.error("Error occured when execute query: " + sql);
throw sqle;
}
return rs;
}

/** *//**
* <pre>
* 执行单一的SQL更新操作,无参数。
* </pre>
*
* @param sql:要执行的SQL更新语句
* @throws SQLException:SQL异常
*/
public synchronized void update(String sql) throws SQLException ...{
update(new String[] ...{ sql }, null);
}

/** *//**
* <pre>
* 执行批量的SQL更新操作,无参数。
* </pre>
*
* @param sqls:要执行的SQL更新语句组
* @throws SQLException:SQL异常
*/
public synchronized void update(String sqls[]) throws SQLException ...{
update(sqls, null);
}

/** *//**
* <pre>
* 执行单一的SQL更新操作,带参数数组
* </pre>
*
* @param sql:要执行的SQL语句
* @param params:预编译语句的参数数组
* @throws SQLException:SQL异常
*/
public synchronized void update(String sql, Object[] params) throws SQLException ...{
update(new String[] ...{ sql }, new Object[][] ...{ params });
}

/** *//**
* <pre>
* 执行批量的SQL更新操作,带参数数组。注意:此处的参数数组是一个二维
* 数组,数组的每一行代表了一个SQL更新语句的参数组。
* </pre>
*
* @param sql:要执行的SQL语句组
* @param params:预编译语句组的参数数组
* @throws SQLException:SQL异常
*/
public synchronized void update(String[] sql, Object[][] params) throws SQLException ...{
logger.debug("Start to execute update.");
int index = 0;
if (con == null) ...{
createConnection();
}
// 记录数据库的当前的自动提交状态
boolean autoCommit = con.getAutoCommit();
try ...{
// 关闭数据库的自动提交
con.setAutoCommit(false);
// 每次执行一个操作
for (index = 0; index < sql.length; index++) ...{
createPreparedStatement(sql[index]);
setParametes(params[index]);
pstm.executeUpdate();
}
// 所有操作执行完毕再一次性提交
con.commit();
} catch (SQLException sqle) ...{
logger.error("Error occured when exceute sql: " + sql[index]);
// 回滚所有操作
con.rollback();
throw sqle;
} finally ...{
con.setAutoCommit(autoCommit);
close();
}
}

/** *//**
* 抽象的插入方法
*
* @param de:数据交换对象
* @throws SQLException:SQL异常
*/
protected abstract void insert(DataExchange de) throws SQLException;

/** *//**
* 抽象的修改方法
*
* @param de:数据交换对象
* @throws SQLException:SQL异常
*/
protected abstract void modify(DataExchange de) throws SQLException;

/** *//**
* 抽象的删除方法
*
* @param de:数据交换对象
* @throws SQLException:SQL异常
*/
protected abstract void delete(DataExchange de) throws SQLException;

/** *//**
* 获取当前记录集的元数据
*
* @param rs:当前的记录集
* @return java.util.List
*/
public List getResultSetData(ResultSet rs) throws SQLException ...{
List<HashMap> list = new ArrayList<HashMap>();
HashMap<String, String> map = null;
logger.debug("Start to get ResultSetMetaData.");
try ...{
ResultSetMetaData rsmd = rs.getMetaData();
int cols = rsmd.getColumnCount();
while (rs.next()) ...{
map = new HashMap<String, String>();
// 将每个字段的key/value对保存到HashMap中
for (int i = 1; i <= cols; i++) ...{
String field = rsmd.getColumnName(i);
String value = rs.getString(i);
map.put(field, value);
}
// 将当前记录添加到List中
list.add(map);
}
} catch (SQLException sqle) ...{
logger.error("Error occured when get ResultSetMetaData");
throw sqle;
} finally ...{
close();
}
return list;
}

/** *//**
* 关闭结果集、预编译语句和返回连接
*
* @throws SQLException:SQL异常
*/
public void close() throws SQLException ...{
logger.debug("Start to close resources.");
try ...{
if (rs != null) ...{
rs.close();
}
if (pstm != null) ...{
pstm.close();
}
if (con != null) ...{
con.close();
}
} catch (SQLException sqle) ...{
logger.error("Error occured when close resources.");
throw sqle;
}
}
}
本文介绍了一个抽象DAO类的设计,该类封装了数据库操作的基本功能,包括连接管理、查询、更新及结果集处理等,并实现了错误处理机制。
1091

被折叠的 条评论
为什么被折叠?



