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; } }}