1. 程式人生 > >7、利用泛型和反射,讓public static T findById(Class clazz, int id)方法,更具一般性

7、利用泛型和反射,讓public static T findById(Class clazz, int id)方法,更具一般性

1、前面講到的findById(int id),只是一個僅僅針對user表的操作,為了使得查詢方法更具有一般性,引入了泛型和反射

2、利用泛型和反射,讓public static <T> T findById(Class<T> clazz, int id)方法,更具一般性.GenericityJDBCUtils的程式碼如下

package com.jdbc.genericity.utils;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import com.jdbc.entity.User;
import com.jdbc.utils.MyJDBCUtils;

public class GenericityJDBCUtils {

	private static Connection conn;
	private static PreparedStatement pstate;
	private static ResultSet rs;
	// 為了程式的更好的解耦合,利用Properties檔案儲存連線Mysql的配置檔案
	private static Properties config = new Properties();
	/**
	 * 使用static塊,載入資料庫的配置檔案和資料庫的驅動
	 */
	static {
		try {
			config.load(MyJDBCUtils.class.getClassLoader().getResourceAsStream(
					"db.properties"));
			Class.forName(config.getProperty("driver"));
		} catch (Exception e) {
			throw new ExceptionInInitializerError(e);
		}
	}

	/**
	 * 獲取一個數據庫的連線
	 * 
	 * @return
	 */
	public static Connection getConnection() {
		Connection conn = null;
		try {
			conn = DriverManager.getConnection(config.getProperty("url"),
					config.getProperty("username"),
					config.getProperty("password"));
		} catch (SQLException e) {
			throw new RuntimeException("獲取連線Mysql資料庫連線失敗");
		}
		return conn;
	}

	/**
	 * 釋放資料庫的連線
	 * 
	 * @param conn
	 * @param st
	 * @param rs
	 */
	public static void release(Connection conn, Statement st, ResultSet rs) {

		if (rs != null) {
			try {
				rs.close();
			} catch (Exception e) {
				throw new RuntimeException("ResultSet關閉異常");
			}
			rs = null;
		}
		if (st != null) {
			try {
				st.close();
			} catch (Exception e) {
				throw new RuntimeException("Statement關閉異常");
			}
			st = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (Exception e) {
				throw new RuntimeException("Connection關閉異常");
			}
			conn = null;
		}

	}

	/**
	 * 
	 * @param clazz
	 *            要返回的型別的位元組碼
	 * @param id
	 *            要查詢記錄在表裡面的id
	 * @return 在資料庫裡面查詢到的記錄,並返回
	 */
	public static <T> T findById(Class<T> clazz, int id) {
		T bean = null;
		// System.out.println(clazz.getSimpleName());
		try {
			bean = clazz.newInstance();
			String tableName = clazz.getSimpleName();
			String sql = "select * from " + tableName + " where id = ? ";
			conn = getConnection();
			pstate = conn.prepareStatement(sql);
			pstate.setInt(1, id);
			rs = pstate.executeQuery();
			if (rs.next()) {
				// 得到結果集的元陣列
				ResultSetMetaData metaData = rs.getMetaData();
				int count = metaData.getColumnCount();
				for (int i = 0; i < count; i++) {
					// 注意jdbc的下標,從1開始
					// 去獲取到資料庫中的列的名稱
					String name = metaData.getColumnName(i + 1);
					// 獲取到,資料庫列對應的數值
					Object value = rs.getObject(name);
					// 反射bean上與列名相同的屬性
					Field f = bean.getClass().getDeclaredField(name);
					f.setAccessible(true);
					f.set(bean, value);
				}

			}
			return bean;

		} catch (Exception e) {
			throw new RuntimeException("在資料庫中,查詢id為" + id + "的User記錄失敗." + e);
		} finally {
			// 釋放資源,關閉與資料庫的連線
			release(conn, pstate, rs);
		}

	}

	/**
	 * 根據傳進來的sql語句,來跟新資料庫的表記錄
	 * 
	 * @param sql
	 * @param args
	 */
	public static void update(String sql, Object[] args) {
		try {
			if (args.length < 0) {
				throw new RuntimeException("Object[] args的陣列長度,不應該為空");
			}
			conn = getConnection();
			pstate = conn.prepareStatement(sql);
			for (int i = 0; i < args.length; i++) {
				pstate.setObject(i + 1, args[i]);
			}
			// 注意要呼叫這個方法
			pstate.executeUpdate();
			// 釋放資源,關閉與資料庫的連線
			release(conn, pstate, rs);
		} catch (Exception e) {
			throw new RuntimeException("更新資料庫中的記錄失敗" + e);
		}
	}

	/**
	 * 根據sql語句來更新資料庫表中的記錄
	 * 
	 * @param sql
	 */
	public static void update(String sql) {
		try {
			conn = getConnection();
			pstate = conn.prepareStatement(sql);
			// 注意要呼叫這個方法
			pstate.executeUpdate();
			// 釋放資源,關閉與資料庫的連線
			release(conn, pstate, rs);
		} catch (Exception e) {
			throw new RuntimeException("更新資料庫中的記錄失敗" + e);
		}
	}

}
3、測試程式碼如下
package com.jdbc.genericity.test;

import org.junit.Test;

import com.jdbc.entity.Person;
import com.jdbc.entity.User;
import com.jdbc.genericity.utils.GenericityJDBCUtils;

public class GenericityJDBCUtilsTest {

	@Test
	public void tenericityJDBCUtilsTest() {
		User user = GenericityJDBCUtils.findById(User.class, 1);
		System.out.println(user);
		Person person = GenericityJDBCUtils.findById(Person.class, 1);
		System.out.println(person);

	}

}

3、資料庫的情況



4、程式執行結果如下