1. 程式人生 > >簡析DBHelper

簡析DBHelper

package com.hjb.dao;

import java.lang.reflect.Method;
import java.sql.Blob;
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 java.util.Map;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DBHelper {
	/**
	 * 獲取連線
	 * 
	 * @return
	 */
	private Connection getConnection() {
		Connection con = null;
		try {
			DataSource ds = (DataSource) new InitialContext().lookup("java:comp/env/yc");
			con = ds.getConnection();
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return con;
	}

	/**
	 * 關閉資源
	 * 
	 * @param con
	 * @param pstmt
	 * @param rs
	 */
	private void close(Connection con, PreparedStatement pstmt, ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (pstmt != null) {
			try {
				pstmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		if (con != null) {
			try {
				con.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 給預編譯語句中的佔位符賦值
	 * 
	 * @param pstmt
	 * @param params
	 */
	public void setParams(PreparedStatement pstmt, Object... params) {
		if (params != null && params.length > 0) {
			for (int i = 0, len = params.length; i < len; i++) {
				try {
					pstmt.setObject(i + 1, params[i]);
				} catch (SQLException e) {
					System.out.println("第" + (i + 1) + "個注值失敗..." + e.getMessage());
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 給預編譯語句中的佔位符賦值
	 * 
	 * @param pstmt
	 * @param params
	 */
	public void setParams(PreparedStatement pstmt, List<Object> params) {
		if (params != null && params.size() > 0) {
			for (int i = 0, len = params.size(); i < len; i++) {
				try {
					pstmt.setObject(i + 1, params.get(i));
				} catch (SQLException e) {
					System.out.println("第" + (i + 1) + "個注值失敗..." + e.getMessage());
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 獲取結果集中的列名
	 * 
	 * @param rsmd
	 * @param count
	 * @return
	 */
	public String[] getColumnNames(ResultSetMetaData rsmd, int count) {
		String[] colNames = null;
		if (rsmd != null) {
			colNames = new String[count];
			try {
				for (int i = 0; i < count; i++) {
					colNames[i] = rsmd.getColumnName(i + 1).toLowerCase();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return colNames;
	}

	/**
	 * 獲取結果集中的列名
	 * 
	 * @param rs
	 * @return
	 * @throws Exception
	 */
	public String[] getColumnNames(ResultSet rs) throws Exception {
		ResultSetMetaData rsmd = rs.getMetaData();
		int len = rsmd.getColumnCount(); // 獲取結果集中列 的數量

		String[] colNames = new String[len];

		// 迴圈取出每個列的列名存放到colNames陣列中
		for (int i = 0; i < len; i++) {
			colNames[i] = rsmd.getColumnName(i + 1).toLowerCase(); // 將每個列名全部轉化為小寫字母
		}

		return colNames;
	}

	/**
	 * 新增操作
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public int update(String sql, Object... params) {
		int result = 0;
		Connection con = null;
		PreparedStatement pstmt = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯的SQL語句賦值
			this.setParams(pstmt, params);

			// 執行語句
			result = pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, null);
		}
		return result;
	}

	/**
	 * 新增操作
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public int update(String sql, List<Object> params) {
		int result = 0;
		Connection con = null;
		PreparedStatement pstmt = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯的SQL語句賦值
			this.setParams(pstmt, params);

			// 執行語句
			result = pstmt.executeUpdate();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, null);
		}
		return result;
	}
	
	/**
	 * 新增操作
	 * @param sqls
	 * @param params
	 * @return
	 */
	public boolean updates(List<String> sqls,List<List<Object>> params){
		boolean bl=false;
		Connection con=null;
		PreparedStatement pstmt=null;
		try {
			if (sqls!=null && sqls.size()>0) {
				con=this.getConnection();
				//關閉事務的自動提交
				con.setAutoCommit(false);
				
				for(int i=0,len=sqls.size();i<len;i++){
					pstmt=con.prepareStatement(sqls.get(i));
					this.setParams(pstmt, params.get(i));
					pstmt.executeUpdate();
				}
				
				//如果所有語句執行完成都沒有錯誤,則提交事務
				con.commit();
				return true;
			}
		} catch (SQLException e) {
			try {
				con.rollback();
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			try {
				con.setAutoCommit(true);
			} catch (SQLException e) {
				e.printStackTrace();
			}
			this.close(con, pstmt, null);
		}
		return bl;
	}

	/**
	 * 查詢
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public List<Map<String, Object>> find(String sql, Object... params) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯語句中的佔位符賦值
			this.setParams(pstmt, params);

			// 獲取結果集
			rs = pstmt.executeQuery();

			ResultSetMetaData rsmd = rs.getMetaData();
			int colCount = rsmd.getColumnCount();

			String[] colNames = this.getColumnNames(rsmd, colCount);

			Map<String, Object> map = null;

			Object obj = null;
			String colType = null;

			while (rs.next()) { //// 每迴圈一次就是一行記錄,我們需要將這行記錄中的值存到一個map中,以列名為鍵,以當前列的值為值
				map = new HashMap<String, Object>();
				for (String col : colNames) {
					obj = rs.getObject(col); // 判斷當前這個列的值的型別

					if (obj != null) {
						colType = obj.getClass().getSimpleName();

						if ("BLOB".equals(colType)) {
							Blob blob = rs.getBlob(col);

							// 將Blob變成一個位元組陣列
							byte[] bt = blob.getBytes(1, (int) blob.length());

							map.put(col, bt);
						} else {
							map.put(col, obj);
						}
					} else {
						map.put(col, obj);
					}
				}
				// 當for迴圈結束,說明這一行資料已經讀完並存到了map中,接下來我們需要將這行資料存到list中
				list.add(map);
				map = null;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, rs);
		}
		return list;
	}

	/**
	 * 查詢
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public List<Map<String, String>> findStr(String sql, Object... params) {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯語句中的佔位符賦值
			this.setParams(pstmt, params);

			// 獲取結果集
			rs = pstmt.executeQuery();

			ResultSetMetaData rsmd = rs.getMetaData();
			int colCount = rsmd.getColumnCount();

			String[] colNames = this.getColumnNames(rsmd, colCount);

			Map<String, String> map = null;

			while (rs.next()) { //// 每迴圈一次就是一行記錄,我們需要將這行記錄中的值存到一個map中,以列名為鍵,以當前列的值為值
				map = new HashMap<String, String>();

				for (String col : colNames) {
					map.put(col, rs.getString(col));
				}
				// 當for迴圈結束,說明這一行資料已經讀完並存到了map中,接下來我們需要將這行資料存到list中
				list.add(map);
				map = null;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, rs);
		}
		return list;
	}

	/**
	 * 查詢
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public List<Map<String, Object>> find(String sql, List<Object> params) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯語句中的佔位符賦值
			this.setParams(pstmt, params);

			// 獲取結果集
			rs = pstmt.executeQuery();

			ResultSetMetaData rsmd = rs.getMetaData();
			int colCount = rsmd.getColumnCount();

			String[] colNames = this.getColumnNames(rsmd, colCount);

			Map<String, Object> map = null;

			Object obj = null;
			String colType = null;

			while (rs.next()) { //// 每迴圈一次就是一行記錄,我們需要將這行記錄中的值存到一個map中,以列名為鍵,以當前列的值為值
				map = new HashMap<String, Object>();
				for (String col : colNames) {
					obj = rs.getObject(col); // 判斷當前這個列的值的型別

					if (obj != null) {
						colType = obj.getClass().getSimpleName();

						if ("BLOB".equals(colType)) {
							Blob blob = rs.getBlob(col);

							// 將Blob變成一個位元組陣列
							byte[] bt = blob.getBytes(1, (int) blob.length());

							map.put(col, bt);
						} else {
							map.put(col, obj);
						}
					} else {
						map.put(col, obj);
					}
				}
				// 當for迴圈結束,說明這一行資料已經讀完並存到了map中,接下來我們需要將這行資料存到list中
				list.add(map);
				map = null;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, rs);
		}
		return list;
	}

	/**
	 * 查詢單行資料
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public Map<String, Object> findSingle(String sql, Object... params) {
		Map<String, Object> map = null;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯語句中的佔位符賦值
			this.setParams(pstmt, params);

			// 獲取結果集
			rs = pstmt.executeQuery();

			if (rs.next()) {
				ResultSetMetaData rsmd = rs.getMetaData();
				int colCount = rsmd.getColumnCount();

				String[] colNames = this.getColumnNames(rsmd, colCount);

				map = new HashMap<String, Object>();

				Object obj = null;
				String colType = null;

				for (String col : colNames) {
					obj = rs.getObject(col); // 判斷當前這個列的值的型別

					if (obj != null) {
						colType = obj.getClass().getSimpleName();

						if ("BLOB".equals(colType)) {
							Blob blob = rs.getBlob(col);

							// 將Blob變成一個位元組陣列
							byte[] bt = blob.getBytes(1, (int) blob.length());

							map.put(col, bt);
						} else {
							map.put(col, obj);
						}
					} else {
						map.put(col, obj);
					}
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, rs);
		}
		return map;
	}
	
	/**
	 * 查詢單行資料,用字串儲存
	 * 
	 * @param sql
	 * @param params
	 * @return
	 */
	public Map<String, String> findSingleByStr(String sql, Object... params) {
		Map<String, String> map = null;
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;

		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯語句中的佔位符賦值
			this.setParams(pstmt, params);

			// 獲取結果集
			rs = pstmt.executeQuery();

			if (rs.next()) {
				ResultSetMetaData rsmd = rs.getMetaData();
				int colCount = rsmd.getColumnCount();

				String[] colNames = this.getColumnNames(rsmd, colCount);

				map = new HashMap<String, String>();

				String obj = null;
				String colType = null;

				for (String col : colNames) {
					obj = rs.getString(col); // 判斷當前這個列的值的型別

					if (obj != null) {
						colType = obj.getClass().getSimpleName();

						if ("BLOB".equals(colType)) {
							Blob blob = rs.getBlob(col);

							// 將Blob變成一個位元組陣列
							byte[] bt = blob.getBytes(1, (int) blob.length());

							map.put(col, String.valueOf(bt));
						} else {
							map.put(col, obj);
						}
					} else {
						map.put(col, obj);
					}
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, rs);
		}
		return map;
	}
	
	/**
	 * 查詢
	 * @param sql
	 * @param c
	 * @param params
	 * @return
	 */
	public <T> List<T> find(String sql, Class<T> c, Object ...params){
		List<T> list=new ArrayList<T>();
		Connection con=null;
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		
		try {
			con=this.getConnection();
			pstmt=con.prepareStatement(sql);
			this.setParams(pstmt,params);
			rs=pstmt.executeQuery();
			//獲取結果集中的列名
			String[] colNames = this.getColumnNames(rs);
			
			//取出給定類所有settet方法
			List<Method> methods=this.getSetter(c);
			
			T t=null;
			Object obj;
			String colName=null;  //資料庫中的列名
			String mname=null;  //方法名
			String typeName=null; //型別名
			
			while(rs.next()){
				t=c.newInstance();  //new UserInfo();
				for(String col:colNames){
					colName="set"+col;  //setusid
					for(Method m:methods){
						mname=m.getName();  //setUsid
						if(mname.equalsIgnoreCase(colName)){  //說明找到了對應的方法
							obj=rs.getObject(col);
							if(obj!=null){  //如果不為空,則獲取這個物件的型別,如果為空則說明這個屬性為空,不需要管
								typeName=obj.getClass().getSimpleName();
								if("BigDecimal".equals(typeName)){   //number(8)  number(10,2)
									try{
										//啟用這個方法注值
										m.invoke(t, rs.getInt(col));
									}catch(Exception e){
										m.invoke(t, rs.getDouble(col));
									}
								}else if("Integer".equals(typeName)){
									m.invoke(t, rs.getInt(col));
								}else{
									m.invoke(t, String.valueOf(obj));
								}
							}
							break;
						}
					}
				}
				list.add(t);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			this.close(con, pstmt, rs);
		}
			
		return list;		
		
	}
	
	/**
	 * 查詢
	 * @param sql
	 * @param c
	 * @param params
	 * @return
	 */
	public <T> List<T> find(String sql, Class<T> c,List<Object> params){
		List<T> list=new ArrayList<T>();
		Connection con=null;
		PreparedStatement pstmt=null;
		ResultSet rs=null;
		
		try {
			con=this.getConnection();
			pstmt=con.prepareStatement(sql);
			this.setParams(pstmt,params);
			rs=pstmt.executeQuery();
			//獲取結果集中的列名
			String[] colNames = this.getColumnNames(rs);
			
			//取出給定類所有settet方法
			List<Method> methods=this.getSetter(c);
			
			T t=null;
			Object obj;
			String colName=null;  //資料庫中的列名
			String mname=null;  //方法名
			String typeName=null; //型別名
			
			while(rs.next()){
				t=c.newInstance();  //new UserInfo();
				for(String col:colNames){
					colName="set"+col;  //setusid
					for(Method m:methods){
						mname=m.getName();  //setUsid
						if(mname.equalsIgnoreCase(colName)){  //說明找到了對應的方法
							obj=rs.getObject(col);
							if(obj!=null){  //如果不為空,則獲取這個物件的型別,如果為空則說明這個屬性為空,不需要管
								typeName=obj.getClass().getSimpleName();
								if("BigDecimal".equals(typeName)){   //number(8)  number(10,2)
									try{
										//啟用這個方法注值
										m.invoke(t, rs.getInt(col));
									}catch(Exception e){
										m.invoke(t, rs.getDouble(col));
									}
								}else if("Integer".equals(typeName)){
									m.invoke(t, rs.getInt(col));
								}else{
									m.invoke(t, String.valueOf(obj));
								}
							}
							break;
						}
					}
				}
				list.add(t);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			this.close(con, pstmt, rs);
		}
		
		return list;		
		
	}
	
	/**
	 * 獲取指定類所有setter方法
	 * @param c
	 * @return
	 */
	public List<Method> getSetter(Class<?> c){
		Method[] methods=c.getMethods();
		List<Method> list=new ArrayList<Method>();
		for(Method method:methods){
			if(method.getName().startsWith("set")){
				list.add(method);
			}
		}
		return list;
	}
	
	/**
	 * 獲取記錄數
	 * @param sql
	 * @param params
	 * @return
	 */
	public int getTotal(String sql,Object ...params){
		Connection con = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		int result=0;
				
		try {
			// 獲取連線
			con = this.getConnection();

			// 執行預編譯語句
			pstmt = con.prepareStatement(sql);

			// 給預編譯語句中的佔位符賦值
			this.setParams(pstmt, params);

			// 獲取結果集
			rs = pstmt.executeQuery();

			if (rs.next()) {
				result=rs.getInt("total");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			this.close(con, pstmt, rs);
		}
		return result;
	}
}