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