1. 程式人生 > >javaWeb_JDBC_利用反射以及JDBC元數據編寫通用的查詢方法

javaWeb_JDBC_利用反射以及JDBC元數據編寫通用的查詢方法

isp rem where lec out 查詢 實體 通用 結果集


JDBC利用反射以及元數據編寫通用的查詢方法[*****]

1.如何獲取元數據
Java 通過JDBC獲得連接以後,得到一個Connection 對象,可以從這個對象獲得有關數據庫管理系統的各種信息,包括數據庫中的各個表,
表中的各個列,數據類型,觸發器,存儲過程等各方面的信息。根據這些信息,JDBC可以訪問一個實現事先並不了解的數據庫。
獲取這些信息的方法都是在DatabaseMetaData類的對象上實現的,而DataBaseMetaData對象是在Connection對象上獲得的。


2.元數據操作類——DatabaseMetaData類
DatabaseMetaData 類中提供了許多方法用於獲得數據源的各種信息,通過這些方法可以非常詳細的了解數據庫的信息:

(1).getURL():返回一個String類對象,代表數據庫的URL。
(2).getUserName():返回連接當前數據庫管理系統的用戶名。
(3).isReadOnly():返回一個boolean值,指示數據庫是否只允許讀操作。
(4).getDatabaseProductName():返回數據庫的產品名稱。
(5).getDatabaseProductVersion():返回數據庫的版本號。
(6).getDriverName():返回驅動驅動程序的名稱。
(7).getDriverVersion():返回驅動程序的版本號。


3.結果集元數據類---ResultSetMetaData 類
(1).ResultSetMetaData 類是可以描述ResultSet的元數據對象,可用於獲取關於 ResultSet 對象中列的類型和屬性信息的對象;

(2).如何獲取ResultSetMetaData對象
調用ResultSet的getMetaData()方法

(3).相關的方法
A.getColumnName(int column):獲取指定列的名稱
B.getColumnCount():返回當前 ResultSet 對象中的列數。
C.getColumnTypeName(int column):檢索指定列的數據庫特定的類型名稱。
D.getColumnDisplaySize(int column):指示指定列的最大標準寬度,以字符為單位。
E.isNullable(int column):指示指定列中的值是否可以為 null。
F.isAutoIncrement(int column):指示是否自動為指定列進行編號,這樣這些列仍然是只讀的

4.編寫通用方法的步驟
(1). 得到 ResultSet 對象
(2). 得到 ResultSetMetaData 對象
(3). 創建一個 Map<String, Object> 對象, 鍵: SQL 查詢的列的別名, 值: 列的值
(4). 處理結果集. 利用 ResultSetMetaData 填充 3 對應的 Map 對象
(5). 若 Map 不為空集, 利用反射創建 clazz 對應的對象


5.代碼實現

//通用方法

/**
* 通用的查詢方法:可以根據傳入的 SQL、Class 對象返回 SQL 對應的記錄的對象
* @param clazz: 描述對象的類型
* @param sql: SQL 語句。可能帶占位符
* @param args: 填充占位符的可變參數。
* @return
*/
public static <T> T get(Class<T> clazz, String sql, Object... args) {
T entity = null;

Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;

try {
//1. 得到 ResultSet 對象
connection = JDBCTools.getConnection();
preparedStatement = connection.prepareStatement(sql);
for (int i = 0; i < args.length; i++) {
preparedStatement.setObject(i + 1, args[i]);
}
resultSet = preparedStatement.executeQuery();

//2. 得到 ResultSetMetaData 對象
ResultSetMetaData rsmd = resultSet.getMetaData();

//3. 創建一個 Map<String, Object> 對象, 鍵: SQL 查詢的列的別名,
//值: 列的值
Map<String, Object> values = new HashMap<>();

//4. 處理結果集. 利用 ResultSetMetaData 填充 3 對應的 Map 對象
if(resultSet.next()){
for(int i = 0; i < rsmd.getColumnCount(); i++){
String columnLabel = rsmd.getColumnLabel(i + 1);
Object columnValue = resultSet.getObject(i + 1);

values.put(columnLabel, columnValue);
}
}

//5. 若 Map 不為空集, 利用反射創建 clazz 對應的對象
if(values.size() > 0){
entity = clazz.newInstance();

//5. 遍歷 Map 對象, 利用反射為 Class 對象的對應的屬性賦值.
for(Map.Entry<String, Object> entry: values.entrySet()){
String fieldName = entry.getKey();
Object value = entry.getValue();
ReflectionUtils.setFieldValue(entity, fieldName, value);
}
}

} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.releaseDB(resultSet, preparedStatement, connection);
}

return entity;
}


//測試代碼
public static void main(String[] args) {
String sql = "SELECT * from student WHERE studentName = ?";
String sql2 = "select id id,studentName studentName,age age,nativePlace nativePlace from student "
+ "where studentName = ?";
Student stu = get(Student.class, sql, "王五");
System.out.println(sql2);
Student stu2 = get(Student.class, sql2, "李四");
System.out.println(stu);
System.out.println(stu2);
}


6.流程轉化關系

數據庫--->記錄--->結果集--->遍歷結果集,獲取結果集中的相關信息--->比較實體對象和結果集中的信息,如果相等,則分別把結果填充
到對應的實體對象的屬性值上,並返回。如果不相等,報出異常。

javaWeb_JDBC_利用反射以及JDBC元數據編寫通用的查詢方法