java學習 -- 利用類的反射和泛型自己動手寫jdbc封裝小類庫
自己動手來封裝jdbc訪問類庫
在公司開發專案(ssh框架)的時候,我特別煩躁的一點就是每次用jdbc方式寫一個資料訪問(hibernate 可以用但是個人覺得對於複雜查詢難以做到和好的控制,可能自己還要慢慢研究吧,自己喜歡mybatis),每次都要寫一大堆模板程式碼,比較繁瑣!
下面說下我的思路。
第一步,分析抽象
從已有的程式碼,出發會發現,訪問資料庫的套路
-->讀取配置檔案(不是必須的,但是專案中這樣做,當然可以tomcat配置資料來源之類的啊)
-->獲取Connection
-->獲取statement或者preparestatement
--->編寫你的sql(這裡說一下,如果你用的statement這裡直接憑藉字元,如果用的preparestatement就是設定引數,以後的sql語句最好不要用statement,因為他很不安全!!一個很大的問題的sql注入!no zuo no die!)
-->執行sql命令
-->封裝結果
-->返回資料
所以,抽象出來,需要做的是
1.抽象出執行查詢和執行更新(update,insert,delete)
2.抽象結果處理
主要完成的就是著兩個問題
第二步,接上一步編寫執行sql的函式
1.sql執行方法
/**
* 執行sql
* @param sql sql文
* @param params 引數
* @return
*/
public static boolean executeSQL(String sql,String...params){
boolean flag = false;
Connection connection = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for(int i = 0,n = params.length;i<n;i++){
statement.setString(i+1, params[i]);
}
statement.execute(sql);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}finally {
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return flag;
}
2.sql的查詢方法
* 查詢結果
* @param sql sql文
* @param params 引數
* @param handler 結果處理集
* @return 返回結果集
*/
public static<T> List<?> queryResult(String sql,String[] params,ResultMapper<T> handler,Class<T> c){
List<Map<String,Object>> results = null;
Connection connection = null;
ResultSet resultSet = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0, n = (params!=null?params.length:0); i < n; i++) {
statement.setString(i, params[i]);
}
resultSet = statement.executeQuery();
if(resultSet!=null){
results = new ArrayList<>();
String[] name = null;
ResultSetMetaData rsm = null;
while(resultSet.next()){
if(rsm==null){
rsm = resultSet.getMetaData();
System.out.println(JSON.toJSONString(rsm));
int count = rsm.getColumnCount();
System.out.println(count);
name = new String[count];
for(int i = 0;i<count;i++){
name[i] = rsm.getColumnName(i+1);
}
}
Map<String, Object> map = new HashMap<>();
// 開始填充值
for(String keys:name){
map.put(keys, resultSet.getString(keys));
}
results.add(map);
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
if(statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if(connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 開始處理結合
List<T> lists = new ArrayList<>();
if(results!=null){
for(Map<String, Object> e:results){
T t = (T) handler.convert(e,c);
lists.add(t);
}
return lists;
}else{
return null;
}
}
第三步,編寫資料對映介面和預設實現類
package com.handkoo.dao;
import java.io.IOException;
import java.io.InputStream;
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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
public class DButils<T> {
private static final Logger logger = LoggerFactory.getLogger(DButils.class);
private static String url = "";
private static String user = "";
private static String password = "";
static {
InputStream inputStream = DButils.class.getResourceAsStream("/jdbc.properties");
Properties properties = new Properties();
try {
properties.load(inputStream);
url = properties.getProperty("url");
user = properties.getProperty("user");
password = properties.getProperty("password");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static Connection getConnection() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection(url, user, password);
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
/**
* 執行sql
*
* @param sql
* sql文
* @param params
* 引數
* @return
*/
public static boolean executeSQL(String sql, String... params) {
boolean flag = false;
Connection connection = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0, n = params.length; i < n; i++) {
statement.setString(i + 1, params[i]);
}
statement.execute(sql);
flag = true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return flag;
}
/**
* 查詢結果
*
* @param sql
* sql文
* @param params
* 引數
* @param handler
* 結果處理集
* @return 返回結果集
*/
public static <T> List<?> queryResult(String sql, String[] params, ResultMapper<T> handler, Class<T> c) {
List<Map<String, Object>> results = null;
Connection connection = null;
ResultSet resultSet = null;
PreparedStatement statement = null;
try {
connection = getConnection();
statement = connection.prepareStatement(sql);
for (int i = 0, n = (params != null ? params.length : 0); i < n; i++) {
statement.setString(i+1, params[i]);
}
resultSet = statement.executeQuery();
if (resultSet != null) {
results = new ArrayList<>();
String[] name = null;
ResultSetMetaData rsm = null;
while (resultSet.next()) {
if (rsm == null) {
rsm = resultSet.getMetaData();
System.out.println(JSON.toJSONString(rsm));
int count = rsm.getColumnCount();
System.out.println(count);
name = new String[count];
for (int i = 0; i < count; i++) {
name[i] = rsm.getColumnName(i + 1);
}
}
Map<String, Object> map = new HashMap<>();
// 開始填充值
for (String keys : name) {
map.put(keys, resultSet.getString(keys));
}
results.add(map);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (resultSet != null) {
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 開始處理結合
List<T> lists = new ArrayList<>();
if (results != null) {
for (Map<String, Object> e : results) {
T t = (T) handler.convert(e, c);
lists.add(t);
}
return lists;
} else {
return null;
}
}
/**
* 型別轉化介面
*
* @author PengChan
*
* @param <T>
*/
public interface ResultMapper<T> {
@SuppressWarnings("hiding")
<T> T convert(Map<String, Object> resource, Class<T> c);
}
/**
* 預設的型別實現
*
* @author PengChan
*
*/
public class DefaultMapper implements ResultMapper<T> {
@SuppressWarnings("hiding")
public <T> T getInstance(Class<T> c) throws InstantiationException, IllegalAccessException {
return c.newInstance();
}
/**
* 轉化的核心方法
*/
@SuppressWarnings("hiding")
@Override
public <T> T convert(Map<String, Object> resource, Class<T> c) {
T t = null;
try {
t = getInstance(c);
// 獲取所有的成員變數
Field[] declaredFields = t.getClass().getDeclaredFields();
// 迴圈遍歷設定值
for (Field f : declaredFields) {
setValute(f, t, resource.get(f.getName()));
}
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
/**
* 設定型別的值
*
* @param fieldType
* @param value
*/
@SuppressWarnings({ "hiding", "rawtypes" })
private <T> void setValute(Field field, T t, Object value) {
try {
Class fieldType = field.getType();
field.setAccessible(true);
if (fieldType.equals(int.class)) {// 如果是整形
field.setInt(t, (int) value);
} else if (fieldType.equals(float.class)) {
field.setFloat(t, (float) value);
} else if (fieldType.equals(boolean.class)) {
field.setBoolean(t, (boolean) value);
} else if (fieldType.equals(double.class)) {
field.setDouble(t, (double) value);
} else if (fieldType.equals(byte.class)) {
field.setByte(t, (byte) value);
} else if (fieldType.equals(short.class)) {
field.setShort(t, (short) value);
} else if (fieldType.equals(long.class)) {
field.setLong(t, (long) value);
} else if (fieldType.equals(char.class)) {
field.setChar(t, (char) value);
} else {
field.set(t, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
呼叫方式:
DButils.queryResult(sql, null, new DButils().new DefaultMapper(), FitType.class);
注意:該工具類有一個侷限性,就是對應的java類的屬性名稱需要與資料庫的名稱一致才能匹配。(如果這樣,還需要配置xml檔案來建立實體類和資料庫表之間的對映,這不在考慮的範圍之內,建議使用mybatis)
執行的結果如下:
以上就是我全部的分析內容了,有的地方還需要完善。
相關文章
- Jdbc 封裝, 利用反射, 加入連線池JDBC封裝反射
- 好程式設計師Java學習路線分享Java案例-封裝JDBC工具類程式設計師Java封裝JDBC
- 如何用反射呼叫泛型類的方法反射泛型
- 泛型類和泛型方法泛型
- TypeScript 泛型介面和泛型類TypeScript泛型
- 自己動手實現Java中的StringBuffer類Java
- LinkedList重寫(5)LinkedList簡單的封裝和增加泛型封裝泛型
- 泛型類派生子類泛型
- 2018-05-19學習小結 - 儲存類的倉庫-Java常用類庫9Java
- 「Laravel 核心學習」類的反射和依賴注入Laravel反射依賴注入
- MFC之動態呼叫自己寫的類庫中的類的成員方法
- 【Java反射】Java 泛型基礎Java反射泛型
- JAVA API:ArrayList(泛型類)基本使用JavaAPI泛型
- Java類的設計和封裝及類成員的訪問控制Java封裝
- Gson泛型封裝泛型封裝
- Java 學習:物件和類Java物件
- Java 包裝類和基本型別Java型別
- 泛型類、泛型方法及泛型應用泛型
- 4、類和物件—封裝物件封裝
- .Net Core利用反射動態載入類庫的方法(解決類庫不包含Nuget依賴包的問題)反射
- 泛型,內部類泛型
- Java列舉類、註解和反射Java反射
- java學習筆記(包裝類)Java筆記
- 泛型類、泛型方法、型別萬用字元的使用泛型型別字元
- 靜態庫封裝之ComStr類封裝
- 靜態庫封裝之ComFile類封裝
- 靜態庫封裝之ComDir類封裝
- 微信、百度、位元組跳動等小程式公共類庫封裝封裝
- Dart4Flutter – 03 – 類和泛型DartFlutter泛型
- java反射呼叫set和get方法的通用類Java反射
- java 匿名 泛型 獲取真實類名Java泛型
- Java學習-封裝Java封裝
- 不如自己寫一個 schema 類庫吧
- java反射之Class類Java反射
- Java反射給泛型集合賦值Java反射泛型賦值
- Java中的類反射機制Java反射
- 【譯】在非泛型類中建立泛型方法泛型
- 關於Java中泛型、反射和註解的掃盲篇Java泛型反射
- 14.Java-Arrays(類)、基本型別包裝類、Integer(類)Java型別