1. 程式人生 > 實用技巧 >基於JDBC封裝資料庫基本CURD操作

基於JDBC封裝資料庫基本CURD操作

在使用jdbc時,我們每進行一次資料庫操作,都會建立連線 關閉連線 如果是查詢操作我們每次都會獲得結果集並對它進行遍歷輸出結果 如果是更新操作那麼我們也得重複寫著可能就幾個引數不一樣的更新語句.這就導致了我們程式碼冗餘度非常高,並且可複用性很差 . 這個時候我們就可以考慮對這些資料庫常規操作封裝成一個工具類,這樣我們以後如果要對資料庫進行常規操作就可以直接呼叫這個工具類的方法,而不需要我們每次操作都要重複把一個程式碼寫很多遍,話不多說,馬上開始講解如何封裝

1.準備屬性檔案: 在src目錄下建立一個新的file檔案,用jdbc.properties命名 然後用鍵值對的形式寫出驅動類路徑,url地址,資料庫使用者名稱,使用者密碼,連線池最長等待時間,初始連線個數,最大同時使用的連線數(這裡使用資料庫連線池技術,減少時間消耗)

2.

public static void init(){
if(ds==null || ds.isClosed()){
new DruidDataSource();
}
try {
Class.forName(DRIVER_CLASS); //mysqljdbc4之後可以不用手動載入驅動路徑,獲取連線的時候能夠自動載入
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
ds.setDriverClassName(DRIVER_CLASS);
ds.setUrl(URL);
ds.setUsername(USER);
ds.setPassword(PASSWORD);
ds.setMaxActive(MAX_ACTIVE);
ds.setInitialSize(INIT_SIZE);
ds.setMaxWait(MAX_WAIT);
}
對連線池物件進行初始化操作


3.返回連線物件
public static synchronized Connection getConn() {
try {
if(ds==null || ds.isClosed()){
init();
}
return ds.getConnection();
} catch (SQLException e){
e.printStackTrace();
}
return null;
}
這裡為了防止多執行緒獲得連線物件造成多個執行緒公用一個連線物件,使用synchronized關鍵字修飾方法


4.關閉連線
public static void close(ResultSet rs,Statement stat,Connection conn){

try {
if(rs != null) rs.close();
if(stat != null)stat.close();
if(conn != null)conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
第二個引數使用 Statement介面,增加引數多型性


5.更新操作封裝(新增,刪除,更改)
public static boolean exeUpdate( Connection conn, String sql,Object...params){


PreparedStatement ps = null;
try {
ps = conn.prepareStatement(sql);
if(params != null){
for (int i = 0; i < params.length; i++) {
ps.setObject(i+1, params[i]);
}
}
return ps.executeUpdate()>0;

} catch (SQLException e) {
e.printStackTrace();
}finally{
close(null, ps, conn);
}

return false;
}
使用者傳進來三個引數,一個是連線物件,一個是sql語句,一個是動態引數陣列(注意:動態引數陣列必須放到引數列表末尾,裡面放置sql語句預處理需要使用到的引數值)

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
在封裝查詢操作前,我們還要做一些準備工作. 1.因為查詢得到的結果集是類似map集合的鍵值對結果,我們不妨定義一個把鍵值對轉化為map集合的方法,(注意:表中一條資料就是一個map
集合,因為map集合的鍵不允許重複,所以我們有必要定義一個以map集合為泛型的List集合,最後再將這個集合返回,如此,我們便拿到了這個表中的所有記錄)2.查詢操作最後返回的肯定是對應實體類的物件(一條)或者物件陣列(多條),所以我們還得定義一個將map集合轉換為對應實體類物件的方法.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6.執行相關查詢操作,返回一個List<Map<String,Object>>集合
public static List<Map<String,Object>> queryMaps(String sql,Object...params){
List<Map<String,Object>> list = new ArrayList<>();
PreparedStatement ps = null;
Connection conn = null;
ResultSet rs = null;
conn = getConn();
try {
ps = conn.prepareStatement(sql);

if(params != null){
for (int i = 0; i < params.length; i++) {
//對ps進行預處理
ps.setObject(i+1, params[i]);
}
}

//取到結果集

rs = ps.executeQuery();
//獲取結果集的元資料物件ResultSetMetaData
ResultSetMetaData rsmd = rs.getMetaData();
//獲取總列數
int columnCount = rsmd.getColumnCount();
//遍歷結果集
while(rs.next()){
//定義一個map,用於裝資料
Map<String,Object> map = new HashMap<String, Object>();
//遍歷獲取每一列的資訊
for (int i = 1; i <= columnCount; i++) {
//獲取列名稱,作為map集合的鍵
String key = rsmd.getColumnName(i);
//獲取列標籤(用於取得列表中的值,因為並不知道使用者有沒有設定別名 所以統一用label)
String label = rsmd.getColumnLabel(i);
//獲得列值
Object value = rs.getObject(label);
if(Objects.nonNull(value))
map.put(key, value);
}
list.add(map);
}
這裡用到了元資料處理相關知識,大家可以看看程式碼上的註釋,解釋的挺詳細

7.將map集合轉換成對應實體類的物件
public static <T> T mapToBean(Map<String,Object>map,Class<T> t){
T obj = null;
try {
//根據我們提供的型別,我們建立一個對應的物件
obj = t.newInstance();
//獲取Class中所有屬性欄位
Field[] fields = t.getDeclaredFields();
//遍歷獲取每一個物件
for (Field f : fields) {
String fname = f.getName();
//獲取屬性值
Object value = map.get(fname);
if(f != null){
//設定屬性物件的可訪問性
f.setAccessible(true);
//設定值
f.set(obj, value);
}
}
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}



return obj;
}
這裡主要運用到了反射的知識,先用傳進來的Class物件構建一個新的實體類物件 然後取得該物件所有的屬性的集合,對該集合遍歷,獲得其中屬性的屬性名當做map集合的鍵值,之後通過通過鍵值獲得map集合的值value,然後將所有屬性設定為可訪問f.setAccessible(true)
,最後使用field中的set(obj,value)方法將map集合中的值傳入變數的屬性中並返回該物件

------------------------------------------
這兩個方法定義完成後,我們就可以定義我們的查詢方法了
------------------------------------------

8.查詢一條資料
public static<T> T queryOne(Class<T> t,String sql,Object...params){
List<Map<String,Object>> list = queryMaps(sql, params);
if(list.size() > 0) {

Map<String,Object> map = list.get(0);
return mapToBean(map, t);

}

return null;
}
9.查詢多條資料public static<T> List<T> queryList(Class<T> t,String sql,Object...param){
   List<T> list = new ArrayList<T>();
List<Map<String,Object>> maps = queryMaps(sql,param);
//遍歷集合中每一條資料(map)
maps.forEach(m->{
//將javabean裝入list
T obj = mapToBean(m, t);
list.add(obj);
});

return list;
}
和查詢單條資料差不多,就是多了一個遍歷的過程

9.查詢資料總條數
public static int queryCount(String sql,Object...params) throws SQLException {

Connection conn = getConn();
PreparedStatement ps = conn.prepareStatement(sql);
/**如果有動態引數陣列的話就要對sql進行預處理*/
if(params != null){
for (int i = 0; i < params.length; i++) {
ps.setObject(i+1, params[i]);
}
}
/**沒有的話,直接執行查詢語句就行了*/
ResultSet rs = ps.executeQuery();
if(rs.next()){
return rs.getInt(1);

}else{

return 0;

}
}

注意這裡指標一定要往下移動一位,不然rs.get(1)取不到值
到此,這個封裝工具類就完成了 下次我們如果要使用資料庫的相關操作可以直接呼叫此類方法 只需修改它的屬性檔案就行了

今天你學到東西了嗎