Java JDBC通用操作基類 (MySQL)數據庫

DBHelper.java

package MySQL;


import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import java.util.Map.Entry;




public class DBHelper {
	
	// 定義共用的連接對象

	private Connection conn;
	
	private boolean isAutoCommit = true;
	static final String JDBC_DRIVER = "com.mysql.cj.jdbc.Driver";
	static final String DB_URL = "jdbc:mysql://localhost:3306/aaa";


	// 數據庫的用戶名與密碼,需要根據自己的設置
	static final String USER = "student";
	static final String PASS = "aaaaaaaa";
	/**
	 * 	類的代碼塊:
	 * 	靜態塊: 
	 * 		static {}
	 * 		特點: 會在類被加載到虛擬機時,執行一次(  例如: import 類)
	 * 	實例塊
	 * 		{}
	 * 		特點: 會在對象被創建時執行一次, 在構造方法前
	 * 	塊不是方法,不能拋出編譯期異常
	 */
	static {
		try {
			Class.forName(JDBC_DRIVER);
		} catch (ClassNotFoundException e) {
			// 異常轉型 ==> 異常鏈
			// 未捕獲的運行期異常將導致程序的終止
			RuntimeException re = new RuntimeException("數據庫驅動加載失敗!", e);
			throw re;
		}
	}
	
	/**
	 * 使用 isAutoCommit 決定是否自動提交
	 * 
	 * 如果是自動提交, 則意味着每次執行 update 方法都要獲取新的連接, 在執行之後關閉連接
	 * 否則, 不關閉連接
	 * @param isAutoCommit  自動提交  true
	 */
	public DBHelper(boolean isAutoCommit) {
		this.isAutoCommit = isAutoCommit;
		if(isAutoCommit == false) {
			conn = openConnection();
		}
	}
	
	/**
	 * JDBC 連接默認是自動提交, 也就是每次執行完增刪改都會自動提交
	 * 無參的構造方法, 可以註釋掉了
	 */
	public DBHelper() {
		// 在構造方法中創建連接
		//conn = openConnection();
	}
	
	// 關閉連接
	public void closeConnection() {
		IOHelper.close(conn);
	}
	
	// 返回連接對象
	public Connection getConn() {
		return conn;
	}

	/**
	 * 	獲取連接
	 * @return
	 */
	public Connection openConnection() {

		try {
			if(isAutoCommit) {
				return DriverManager.getConnection(DB_URL,USER,PASS);
			} else {
				if(conn == null) {
					// 禁止自動提交
					conn = DriverManager.getConnection(DB_URL,USER,PASS);
					conn.setAutoCommit(isAutoCommit);
				}
				return conn;
			}
		} catch (SQLException e) {
			throw new RuntimeException("獲取數據庫連接失敗!", e);
		}
	}

	/**
	 * 	執行修改數據庫的語句
	 * sql = "update emp set ename = ? where empno=?"
	 * update(sql,2,3,)
	 * @param sql		執行的sql語句
	 * @param params	可變參數數組
	 * @return
	 */
	public int update(String sql, Object... params) {
		try {
			// 每次都會通過open方法獲取連接
			conn = openConnection(); 
			System.out.println("SQL: " + sql);
			PreparedStatement ps = conn.prepareStatement(sql);
			// alrt + /
			System.out.println("參數: " + Arrays.toString(params));
			for (int i = 0; i < params.length; i++) {
				ps.setObject(i + 1, params[i]);
			}
			return ps.executeUpdate();
		} catch (SQLException e) {
			throw new RuntimeException("執行SQL語句失敗!", e);
		} finally {
			if(isAutoCommit == true) {
				IOHelper.close(conn);
			}
		}
	}

	/**
	 * 	執行查詢語句
	 * @param sql
	 * @param params
	 * @return
	 */
	public List<Map<String, Object>> query(String sql, Object... params) {
		try {
			conn = openConnection(); 
			System.out.println("SQL: " + sql);
			PreparedStatement ps = conn.prepareStatement(sql);
			// alrt + /
			System.out.println("參數: " + Arrays.toString(params));
			for (int i = 0; i < params.length; i++) {
				ps.setObject(i + 1, params[i]);
			}
			ResultSet rs = ps.executeQuery();

			// 獲取結果集元數據對象, 元(Meta)數據(data): 描述數據的數據
			ResultSetMetaData rsmd = rs.getMetaData();
			// 創建返回結果對象
			List<Map<String, Object>> ret = new ArrayList<>();
			while (rs.next()) {
				// 創建 map 集合
				/**
				 * 1. HashMap   	無序不重複
				 * 2 LinkedHashMap, 有序不重複
				 * 3. TreeMap 		排序不重複
				 */
				Map<String, Object> row = new LinkedHashMap<>();
				// 獲取每一個字段值, 設置到一個map中
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String columnName = rsmd.getColumnName(i + 1);
					Object columnValue = rs.getObject(columnName);
					row.put(columnName, columnValue);
				}
				// 將 map 添加到 ret 中
				ret.add(row);
			}
			return ret;
		} catch (SQLException e) {
			throw new RuntimeException("執行SQL語句失敗!", e);
		} finally {
			if(isAutoCommit == true) {
				IOHelper.close(conn);
			}
		}
	}
	
	/**
	 * 	返回值的類型是可變的類型, 所有的集合==> 泛型類
	 * 	query 方法改造成 泛型方法	: 語法的定義: 在方法前用 <E>
	 * 
	 * @param sql
	 * @param cls		類對象, 表示 E 類的類對象, Java 反射技術
	 * @param params
	 * @return
	 */
	public <E> List<E> query(String sql, Class<E> cls, Object... params) {
		try {
			conn = openConnection();
			System.out.println("SQL: " + sql);
			PreparedStatement ps = conn.prepareStatement(sql);
			// alrt + /
			System.out.println("參數: " + Arrays.toString(params));
			for (int i = 0; i < params.length; i++) {
				ps.setObject(i + 1, params[i]);
			}
			ResultSet rs = ps.executeQuery();

			// 獲取結果集元數據對象, 元(Meta)數據(data): 描述數據的數據
			ResultSetMetaData rsmd = rs.getMetaData();
			// 創建返回結果對象
			List<E> ret = new ArrayList<>();
			while (rs.next()) {
				// 創建 實體對象集合( 通過反射機制創建實體對象  == new 實體類()   )
				E e;
				try {
					e = cls.newInstance();
				} catch (Exception e2) {
					// 異常轉型
					throw new RuntimeException(e2);
				}
				
				// 通過反射進行屬性值的設置
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					try {
						// 根據當前的列名找對應的屬性
						String columnName = rsmd.getColumnName(i+1); // ID, NAME, AUTHER ...
						columnName = columnName.toLowerCase(); // 轉小寫
						// 獲取該類定義的屬性(包括私有)
						Field field = cls.getDeclaredField(columnName);
						// 獲取當前列的值
						/**
						 *  ID ==> JDBC 數據類型 : BigDecimal 大實數 表示任意大小的數字
						 *  	  	    實體類類型: Long
						 *  .getType 獲取屬性的類型  ==> LONG  String  Integer
						 */
						// 從結果取出的數值
						//Object value = rs.getObject(i+1);  
						// 要轉換的數值
						Object destValue = null;
						// 一定要判斷非空, 否則會導致類型轉換錯誤
//						if(value==null) {
//							continue;
//						}
						if(field.getType().equals(Long.class)) {
							destValue = rs.getLong(i+1);  
							//destValue = Long.valueOf(value + "");
						} else if(field.getType().equals(Integer.class)) {
							destValue = rs.getInt(i+1);  
							//destValue = Integer.valueOf(value + "");
						} else if(field.getType().equals(Double.class)) {
							destValue = rs.getDouble(i+1);  
							//destValue = Double.valueOf(value + "");
						} else if(field.getType().equals(Byte.class)) {
							destValue = rs.getByte(i+1);  
							//destValue = Byte.valueOf(value + "");
						} else if(field.getType().equals(Boolean.class)) {
							destValue = rs.getBoolean(i+1);  
							//destValue = Boolean.valueOf(value + "");
						} else if(field.getType().equals(Timestamp.class)) {
							destValue = rs.getTimestamp(i+1);  
							//destValue = Byte.valueOf(value + "");
							
						// 其他數據類型請自行添加
						} else {
							destValue = rs.getObject(i+1);  
						}
						// 設置強制訪問私有屬性
						field.setAccessible(true);
						// 將值設置到該屬性中
						field.set(e, destValue);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 將 map 添加到 ret 中
				ret.add(e);
			}
			return ret;
		} catch (SQLException e) {
			throw new RuntimeException("執行SQL語句失敗!", e);
		} finally {
			if(isAutoCommit == true) {
				IOHelper.close(conn);
			}
		}
	}
	
	public List<Map<String, Object>> query1( String sql,Class<Map<String, Object>> cls, Object... params) {
		try {
			conn = openConnection();
			System.out.println("SQL: " + sql);
			PreparedStatement ps = conn.prepareStatement(sql);
			// alrt + /
			System.out.println("參數: " + Arrays.toString(params));
			for (int i = 0; i < params.length; i++) {
				ps.setObject(i + 1, params[i]);
			}
			ResultSet rs = ps.executeQuery();

			// 獲取結果集元數據對象, 元(Meta)數據(data): 描述數據的數據
			ResultSetMetaData rsmd = rs.getMetaData();
			// 創建返回結果對象
			List<Map<String, Object>> ret = new ArrayList<>();
			while (rs.next()) {
				// 創建 實體對象集合( 通過反射機制創建實體對象  == new 實體類()   )
				Map<String, Object> e;
				try {
					e = cls.newInstance();
				} catch (Exception e2) {
					// 異常轉型
					throw new RuntimeException(e2);
				}
				
				// 通過反射進行屬性值的設置
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					try {
						// 根據當前的列名找對應的屬性
						String columnName = rsmd.getColumnName(i+1);
						// ID, NAME, AUTHER ...
						columnName = columnName.toLowerCase();
						// 轉小寫
						// 獲取該類定義的屬性(包括私有)
						Field field = cls.getDeclaredField(columnName);
						// 獲取當前列的值
						/**
						 *  ID ==> JDBC 數據類型 : BigDecimal 大實數 表示任意大小的數字
						 *  	  	    實體類類型: Long
						 *  .getType 獲取屬性的類型  ==> LONG  String  Integer
						 */
						// 從結果取出的數值
						//Object value = rs.getObject(i+1);  
						// 要轉換的數值
						Object destValue = null;
						// 一定要判斷非空, 否則會導致類型轉換錯誤
//						if(value==null) {
//							continue;
//						}
						if(field.getType().equals(Long.class)) {
							destValue = rs.getLong(i+1);  

						} else if(field.getType().equals(Integer.class)) {
							destValue = rs.getInt(i+1);  

						} else if(field.getType().equals(Double.class)) {
							destValue = rs.getDouble(i+1);  

						} else if(field.getType().equals(Byte.class)) {
							destValue = rs.getByte(i+1);  

						} else if(field.getType().equals(Boolean.class)) {
							destValue = rs.getBoolean(i+1);  

						} else if(field.getType().equals(Timestamp.class)) {
							destValue = rs.getTimestamp(i+1);
						// 其他數據類型請自行添加
						} else {
							destValue = rs.getObject(i+1);  
						}
						// 設置強制訪問私有屬性
						field.setAccessible(true);
						// 將值設置到該屬性中
						field.set(e, destValue);
					} catch (Exception e1) {
						e1.printStackTrace();
					}
				}
				// 將 map 添加到 ret 中
				ret.add(e);
			}
			return ret;
		} catch (SQLException e) {
			throw new RuntimeException("執行SQL語句失敗!", e);
		} finally {
			if(isAutoCommit == true) {
				IOHelper.close(conn);
			}
		}
	}
}

IOHelper.java

package MySQL;


import java.io.Closeable;
import java.io.IOException;

/**
 * IO工具類
 */
public class IOHelper {

	/**
	 * 	關閉流的工具方法,  所有的流都實現了 Closeable 方法, 所以都有close 方法, 也就是說:
	 * 	Closeable 是所有流的父類,  這裏使用的就是OOP多態性
	 * @param c
	 */
	public static void close(AutoCloseable c) {
		if (c != null) {
			/**
			 * 	關於如何打開錯誤解決窗口
			 * 	1, 鼠標停在 報錯 點上, eclipse 會給出解決方案, 其中就包括 try
			 * 	2, 光標停在 報錯 點上  ctrl + 1
			 */
			try {
				c.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}

測試

建表語句

create table Student(
     Sno int not null auto_increment primary key,
     Sname varchar(10) not null,
     Sex char(1) not null,
     Sage tinyint(100) not null,
     Sdept char(4) not null)comment = '學生表';
		 

insert into Student (Sname, Sex, Sage, Sdept) values ('李勇', '男', 20, 'CS');
insert into Student (Sname, Sex, Sage, Sdept) values ('劉晨', '女', 19, 'CS');
insert into Student (Sname, Sex, Sage, Sdept) values ('王敏', '女', 18, 'MA');
insert into Student (Sname, Sex, Sage, Sdept) values ('張立', '男', 19, 'IS');

COMMIT;
SELECT * FROM Student;

結果
在這裏插入圖片描述

test.java

package MySQL;

import java.util.List;
import java.util.Map;

public class test {
    public static void main(String[] args) {
        DBHelper dbHelper = new DBHelper();
        //查詢數據
        List<Map<String, Object>> list = dbHelper.query("select * from Student;");
        //UPDATE <表名> SET 字段 1=值 1 [,字段 2=值 2… ] [WHERE 子句 ]
        System.out.println(list);

        //修改數據
        String sql = "update Student set sex= ? where sno=?";
        dbHelper.update(sql,"女","1");
        List<Map<String, Object>> list2 = dbHelper.query("select * from Student;");
        System.out.println(list2);

        //增加數據INSERT INTO <表名> [ <列名1> [ , … <列名n>] ] VALUES (值1) [… , (值n) ];
        sql = "insert into Student (Sname, Sex, Sage, Sdept) values (?, ?, ?, ?)";
        dbHelper.update(sql,"蔡碧", "男", "12","CN");
        List<Map<String, Object>> list3 = dbHelper.query("select * from Student;");
        System.out.println(list3);

        //刪除數據 DELETE FROM <表名> [WHERE 子句] [ORDER BY 子句] [LIMIT 子句]
        sql = "delete from Student where sno = ?";
        dbHelper.update(sql,2);
        List<Map<String, Object>> list4 = dbHelper.query("select * from Student;");
        System.out.println(list4);

    }

}

輸出結果

SQL: select * from Student;
參數: []
[{Sno=1, Sname=李勇, Sex=男, Sage=20, Sdept=CS}, {Sno=2, Sname=劉晨, Sex=女, Sage=19, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=張立, Sex=男, Sage=19, Sdept=IS}]
SQL: update Student set sex= ? where sno=?
參數: [女, 1]
SQL: select * from Student;
參數: []
[{Sno=1, Sname=李勇, Sex=女, Sage=20, Sdept=CS}, {Sno=2, Sname=劉晨, Sex=女, Sage=19, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=張立, Sex=男, Sage=19, Sdept=IS}]
SQL: insert into Student (Sname, Sex, Sage, Sdept) values (?, ?, ?, ?)
參數: [蔡碧, 男, 12, CN]
SQL: select * from Student;
參數: []
[{Sno=1, Sname=李勇, Sex=女, Sage=20, Sdept=CS}, {Sno=2, Sname=劉晨, Sex=女, Sage=19, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=張立, Sex=男, Sage=19, Sdept=IS}, {Sno=5, Sname=蔡碧, Sex=男, Sage=12, Sdept=CN}]
SQL: delete from Student where sno = ?
參數: [2]
SQL: select * from Student;
參數: []
[{Sno=1, Sname=李勇, Sex=女, Sage=20, Sdept=CS}, {Sno=3, Sname=王敏, Sex=女, Sage=18, Sdept=MA}, {Sno=4, Sname=張立, Sex=男, Sage=19, Sdept=IS}, {Sno=5, Sname=蔡碧, Sex=男, Sage=12, Sdept=CN}]

Process finished with exit code 0

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章