优化的 JAVA 通用数据库dao

08/28/2010

之前我曾经放出过一篇《MVC 设计模式中需要的 通用数据库dao》,但是其也有一定的局限性!
例如当数据库连接的驱动 数据库名称 连接用户名 连接密码等发生变化的时候,需要重新编译类库。
现在我们对之前的DAO进行如下的改动,使用资源配置文件的形式保存驱动 数据库名称 连接用户名 连接密码使该类库更方便

  • db.properties资源配置文件内容
  • driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/books
    user=root
    password=1111
  • 实现读取配置文件 db.properties 的静态类
  • package net.royakon.dao;
    /**
     * 实现读取配置文件 db.properties 的静态类
     */
    
    import java.io.InputStream;
    import java.util.Properties;
    
    public final class Env extends Properties{
    
    	//定义变量
    	private static Env instance;
    
    	//以单例模式创建,获得对象实例
    	public static Env getInstance() {
    		if (instance != null) {
    			return instance;
    		}
    		else {
    			makeInstance();
    			return instance;
    		}
    	}
    
    	//同步方法,保证再同一时间,只能被一个调用
    	private static synchronized void makeInstance() {
    		if (instance == null) {
    			instance = new Env();
    		}
    	}
    
    	//调用文件的方法
    	private Env () {
    		InputStream is = getClass().getResourceAsStream("/db.properties");
    		try {
    			load(is);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    }
  • 通用的JDBC数据库访问类
  • package cn.net.royakon.dao;
    
    /**
     * 功能:通用的JDBC数据库访问类
     */
    import java.util.*;
    import java.sql.*;
    import javax.servlet.jsp.jstl.sql.*;
    import cn.net.royakon.dao.Env;
    
    public abstract class GenericDao {
    	// 定义数据库连接
    	private Connection conn;
    
    	// 定义sql语句
    	private String sqlValue;
    
    	// 定义sql语句参数列表
    	private List values;
    
    	/**
    	 * 打开连接
    	 */
    	private void openConnection() {
    		try {
    			String driverClassName = Env.getInstance().getProperty("driver");
    			String url = Env.getInstance().getProperty("url");
    			String user = Env.getInstance().getProperty("user");
    			String password =Env.getInstance().getProperty("password");
    
    			Class.forName(driverClassName).newInstance();
    			conn = DriverManager.getConnection(url , user , password);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	}
    
    	/**
    	 * 设定SQL语句
    	 */
    	public void setSqlValue(String sqlValue) {
    		this.sqlValue = sqlValue;
    	}
    
    	/**
    	 * 设定SQL语句的参数列表
    	 */
    	public void setValues(List values) {
    		this.values = values;
    	}
    
    	/**
    	 * 将SQL语句参数列表中的值赋给预执行语句.
    	 *
    	 * @param pstmt
    	 *            预执行语句
    	 * @param values
    	 *            sql语句参数列表
    	 */
    	private void setValues(PreparedStatement pstmt, List values)
    			throws SQLException {
    		// 循环,将SQL语句参数列表中的值依次赋给预执行语句
    		for (int i = 0; i < values.size(); i++) {
    			Object v = values.get(i);
    			// 注意,setObject()方法的索引值从1开始,所以有i+1
    			pstmt.setObject(i + 1, v);
    		}
    	}
    
    	/**
    	 * 执行查询
    	 *
    	 * @return a javax.servlet.jsp.jstl.sql.Result
    	 * 				  返回Result对象result
    	 * @exception SQLException
    	 *                定义sql异常
    	 */
    	public Result executeQuery() throws SQLException {
    
    		// 定义属性
    		Result result = null;
    		ResultSet rs = null;
    		PreparedStatement pstmt = null;
    		Statement stmt = null;
    		openConnection();
    		try {
    			if (values != null && values.size() > 0) {
    				// 使用预处理语句,并设定所有的sql语句所有参数值
    				pstmt = conn.prepareStatement(sqlValue);
    				setValues(pstmt, values);
    				// 执行查询sql语句,返回查询结果集
    				rs = pstmt.executeQuery();
    			} else {
    				stmt = conn.createStatement();
    				rs = stmt.executeQuery(sqlValue);
    			}
    			// 把ResultSet转换为Result
    			result = ResultSupport.toResult(rs);
    		} finally {
    			// 释放资源
    			if (rs != null) {
    				try {
    					rs.close();
    				} catch (SQLException e) {
    				}
    			}
    			if (stmt != null) {
    				try {
    					stmt.close();
    				} catch (SQLException e) {
    				}
    			}
    			if (pstmt != null) {
    				try {
    					pstmt.close();
    				} catch (SQLException e) {
    				}
    			}
    			if (conn != null) {
    				try {
    					conn.close();
    				} catch (SQLException e) {
    				}
    			}
    		}
    		return result;
    	}
    
    	/**
    	 * 执行Update语句
    	 *
    	 * @return numOfRows
    	 * 				  返回受影响的行数
    	 * @exception SQLException
    	 *                定义sql异常
    	 */
    	public int executeUpdate() throws SQLException {
    		// 定义属性
    		int numOfRows = 0;
    		ResultSet rs = null;
    		PreparedStatement pstmt = null;
    		Statement stmt = null;
    		openConnection();
    		try {
    			if (values != null && values.size() > 0) {
    				// 使用预处理语句,并设定所有的sql语句所有参数值
    				pstmt = conn.prepareStatement(sqlValue);
    				setValues(pstmt, values);
    				numOfRows = pstmt.executeUpdate();
    			} else {
    				// 执行更新sql语句,返回受影响的行数
    				stmt = conn.createStatement();
    				numOfRows = stmt.executeUpdate(sqlValue);
    			}
    		} finally {
    			// 释放资源
    			if (rs != null) {
    				try {
    					rs.close();
    				} catch (SQLException e) {
    				}
    			}
    			if (stmt != null) {
    				try {
    					stmt.close();
    				} catch (SQLException e) {
    				}
    			}
    			if (pstmt != null) {
    				try {
    					pstmt.close();
    				} catch (SQLException e) {
    				}
    			}
    			if (conn != null) {
    				try {
    					conn.close();
    				} catch (SQLException e) {
    				}
    			}
    		}
    		return numOfRows;
    	}
    }