在學框架之前,寫項目時總是要花大量的時間去寫資料庫操作層代碼,這樣會大大降低我們的效率,為瞭解決這個問題,我花了兩天時間利用反射機制和泛型將DAO層進行了封裝,這樣我們只需要寫sql語句,不需要再寫繁瑣的資料庫操作語句,增強代碼的復用性,讓我們把主要精力放在業務邏輯上。 以下就是我寫的代碼(我是用連 ...
在學框架之前,寫項目時總是要花大量的時間去寫資料庫操作層代碼,這樣會大大降低我們的效率,為瞭解決這個問題,我花了兩天時間利用反射機制和泛型將DAO層進行了封裝,這樣我們只需要寫sql語句,不需要再寫繁瑣的資料庫操作語句,增強代碼的復用性,讓我們把主要精力放在業務邏輯上。
以下就是我寫的代碼(我是用連接池操作,普通的jdbc操作和連接池道理相同,主要思想是將結果集設置到對象的屬性中)
1 /** 2 * 預處理通用查詢對象集合 3 * 4 * @param cla 操作類型 5 * @param params 預處理參數 6 * @param sql 要執行的sql語句 7 * @return 返回的對象集合 8 * @throws SQLException 拋出異常 9 */ 10 @SuppressWarnings("deprecation") 11 public static <T> List<T> commonPreparedQueryList(final Class<T> cla,Object params[],String sql) throws SQLException{ 12 //獲得連接池(這裡使用的是阿裡巴巴開源的jar包) 13 QueryRunner qr = new QueryRunner(DBUtil.getDruid()); 14 /* 15 * 聲明一個List存放返回對象 16 */ 17 List<T> tList = new ArrayList<T>(); 18 /* 19 * 執行查詢操作並返回對應集合,傳入sql和預處理參數併進行結果集處理(這裡要實現handle方法) 20 */ 21 tList = qr.query(sql, params,new ResultSetHandler<List<T>>(){ 22 23 public List<T> handle(ResultSet rs) throws SQLException { 24 /* 25 * 這裡要用到ResultSetMetaData來獲取資料庫表的欄位名和數量 26 */ 27 ResultSetMetaData ms = rs.getMetaData(); 2 T t = null;//聲明一個泛型,此處類型和傳入一致 29 List<T> list = new ArrayList<T>(); 30 /* 31 * 通過迴圈獲得表中所有的欄位名,並通過反射的方式把欄位名內容 32 * 設置到我們要查詢的集合中,並將結果返回 33 * 註意:這裡需要用到迴圈的嵌套,我們需要先迴圈表中所有數據, 34 * 然後再迴圈表的所有欄位名 35 */ 36 while(rs.next()){ 37 try { 38 t = cla.newInstance();//創建一個實例化對象 39 //獲得所有欄位名,並將其轉換為駝峰式命名規則 eg:guest_id轉化為guestId 40 for(int i = 0; i <ms.getColumnCount(); i++){ 41 String columnName = ms.getColumnName(i+1);//獲得欄位名 42 /* 43 * 以下操作是將下劃線形式轉化為駝峰式的實現 44 * 現將欄位名以下劃線分割到字元串數組中,將第一個數組元素複製到StringBuffer中 45 * 然後將後面的數組元素第一個首字母轉化為大寫形式,最後將他們拼接到一起,將所得結果轉化為字元串 46 */ 47 String[] strName = columnName.split("_"); 48 StringBuffer sb = new StringBuffer(strName[0]); 49 for(int i1 = 1;i1<strName.length;i1++){ 50 strName[i1] = strName[i1].substring(0, 1).toUpperCase().concat(strName[i1].substring(1)); 51 sb.append(strName[i1]); 52 } 53 String property = sb.toString(); 54 /* 55 * 獲得對象的所有屬性,並將結果集中的內容通過反射賦值到對象的屬性中 56 */ 57 Field field = cla.getDeclaredField(property); 58 field.setAccessible(true); 59 field.set(t, rs.getObject(columnName)); 60 } 61 } catch (InstantiationException e) { 62 e.printStackTrace(); 63 } catch (IllegalAccessException e) { 64 e.printStackTrace(); 65 } catch (NoSuchFieldException e) { 66 e.printStackTrace(); 67 } catch (SecurityException e) { 68 e.printStackTrace(); 69 } 70 //將對象添加到List中 71 list.add(t); 72 } 73 //迴圈結束後返回對象集合 74 return list; 75 } 76 77 }); 78 return tList; 79 }
測試代碼:
1 public void Test() throws SQLException{ 2 List<Book> bookList = new LinkedList<Book>(); 3 Object params[] = new Object[]{"%三%"}; 4 String sql = "select * from book where book_name like ? "; 5 bookList = CommonDao.commonPreparedQueryList(Book.class,params ,sql); 6 System.out.println(bookList); 7 }
一共兩條數據
查詢一條數據(這個和查詢集合的區別隻有集合需要迴圈結果集,而這個只需要用if語句判斷一下即可,其餘代碼完全相同):
1 /** 2 * 通用預處理查詢對象 3 * 4 * @param cla 5 * @param params 6 * @param sql 7 * @return 對象 8 * @throws SQLException 9 * @throws InstantiationException 10 * @throws IllegalAccessException 11 */ 12 @SuppressWarnings("deprecation") 13 public static <T> T commonPreparedQuery(final Class<T> cla,Object params[],String sql) throws SQLException, InstantiationException, IllegalAccessException{ 14 QueryRunner qr = new QueryRunner(DBUtil.getDruid()); 15 T m = cla.newInstance(); 16 m = qr.query(sql,params ,new ResultSetHandler<T>(){ 17 18 public T handle(ResultSet rs) throws SQLException { 19 ResultSetMetaData rm = rs.getMetaData(); 20 T t = null; 21 try { 22 if(rs.next()){ //這裡用if,是與查詢集合代碼的唯一區別 23 t = cla.newInstance(); 24 for(int i = 0; i<rm.getColumnCount(); i++){ 25 String columnName = rm.getColumnName(i+1); 26 String str[] = columnName.split("_"); 27 StringBuffer sb = new StringBuffer(str[0]); 28 for(int j = 1; j<str.length; j++){ 29 str[j] = str[j].substring(0, 1).toUpperCase().concat(str[j].substring(1)); 30 sb.append(str[j]); 31 } 32 String property = sb.toString(); 33 Field field = cla.getDeclaredField(property); 34 field.setAccessible(true); 35 field.set(t, rs.getObject(columnName)); 36 } 37 }else{ 38 System.out.println("sql語句錯誤或對象不存在"); 39 } 40 } catch (InstantiationException e) { 41 e.printStackTrace(); 42 } catch (IllegalAccessException e) { 43 e.printStackTrace(); 44 } catch (SecurityException e) { 45 e.printStackTrace(); 46 } catch (NoSuchFieldException e) { 47 e.printStackTrace(); 48 } 49 return t; 50 } 51 52 }); 53 return m; 54 }
測試:
public void Test() throws SQLException, InstantiationException, IllegalAccessException{ Book book = new Book(); Object params[] = new Object[]{10001}; String sql = "select * from book where book_id = ? "; book = CommonDao.commonPreparedQuery(Book.class, params, sql); System.out.println(book); }
還有普通查詢操作(不通過預處理)
這種方式和預處理查詢的唯一區別隻是不需要傳遞參數params,其餘和上面代碼完全一致
1 /** 2 * 通用類查詢集合 3 * 4 * @param cla 5 * @param sql 6 * @return 7 * @throws SQLException 8 */ 9 public static <T> List<T> commonQueryList(final Class<T> cla,String sql) throws SQLException{ 10 QueryRunner qr = new QueryRunner(DBUtil.getDruid()); 11 List<T> tList = new ArrayList<T>(); 12 tList = qr.query(sql, new ResultSetHandler<List<T>>(){ 13 14 public List<T> handle(ResultSet rs) throws SQLException { 15 ResultSetMetaData ms = rs.getMetaData(); 16 T t = null; 17 List<T> list = new ArrayList<T>(); 18 while(rs.next()){ 19 try { 20 t = cla.newInstance(); 21 for(int i = 0; i <ms.getColumnCount(); i++){ 22 String columnName = ms.getColumnName(i+1); 23 String[] strName = columnName.split("_"); 24 StringBuffer sb = new StringBuffer(strName[0]); 25 for(int i1 = 1;i1<strName.length;i1++){ 26 strName[i1] = strName[i1].substring(0, 1).toUpperCase().concat(strName[i1].substring(1)); 27 sb.append(strName[i1]); 28 } 29 String property = sb.toString(); 30 Field field = cla.getDeclaredField(property); 31 field.setAccessible(true); 32 field.set(t, rs.getObject(columnName)); 33 } 34 } catch (InstantiationException e) { 35 e.printStackTrace(); 36 } catch (IllegalAccessException e) { 37 e.printStackTrace(); 38 } catch (NoSuchFieldException e) { 39 e.printStackTrace(); 40 } catch (SecurityException e) { 41 e.printStackTrace(); 42 } 43 list.add(t); 44 } 45 return list; 46 } 47 48 }); 49 return tList; 50 }
測試:
public void Test() throws SQLException{ List<Book> bookList = new LinkedList<Book>(); String sql = "select * from book "; bookList = CommonDao.commonQueryList(Book.class,sql); System.out.println(bookList); }
同樣有兩條數據
查詢一個對象:
1 /** 2 * 查詢一個資料庫類操作 3 * 4 * @param cla 5 * @param sql 6 * @return 一個資料庫類對象 7 * @throws SQLException 8 * @throws InstantiationException 9 * @throws IllegalAccessException 10 */ 11 public static <T> T commonQuery(final Class<T> cla,String sql) throws SQLException, InstantiationException, IllegalAccessException{ 12 QueryRunner qr = new QueryRunner(DBUtil.getDruid()); 13 T m = cla.newInstance(); 14 m = qr.query(sql, new ResultSetHandler<T>(){ 15 16 public T handle(ResultSet rs) throws SQLException { 17 ResultSetMetaData rm = rs.getMetaData(); 18 T t = null; 19 try { 20 if(rs.next()){ 21 t = cla.newInstance(); 22 for(int i = 0; i<rm.getColumnCount(); i++){ 23 String columnName = rm.getColumnName(i+1); 24 String str[] = columnName.split("_"); 25 StringBuffer sb = new StringBuffer(str[0]); 26 for(int j = 1; j<str.length; j++){ 27 str[j] = str[j].substring(0, 1).toUpperCase().concat(str[j].substring(1)); 28 sb.append(str[j]); 29 } 30 String property = sb.toString(); 31 Field field = cla.getDeclaredField(property); 32 field.setAccessible(true); 33 field.set(t, rs.getObject(columnName)); 34 } 35 }else{ 36 System.out.println("sql語句錯誤或對象不存在"); 37 } 38 } catch (InstantiationException e) { 39 e.printStackTrace(); 40 } catch (IllegalAccessException e) { 41 e.printStackTrace(); 42 } catch (SecurityException e) { 43 e.printStackTrace(); 44 } catch (NoSuchFieldException e) { 45 e.printStackTrace(); 46 } 47 return t; 48 } 49 50 }); 51 return m; 52 }
測試:
@Test public void Test() throws SQLException, InstantiationException, IllegalAccessException{ Book book = new Book(); String sql = "select * from book where book_id = 10002"; book = CommonDao.commonQuery(Book.class,sql); System.out.println(book); }
接下來是增刪改操作,這個操作比較簡單,不需要用到泛型和反射,只需要傳入sql語句即可:
1 public static boolean updateSql(String sql) throws SQLException{ 2 boolean flag = false; 3 QueryRunner qr = new QueryRunner(DBUtil.getDruid());
//執行修改操作 4 if(qr.update(sql)>0) 5 flag = true; 6 return flag; 7 }
還有預處理形式
1 public static boolean updatePreparedSql(String sql,Object params[]) throws SQLException{ 2 boolean flag = false; 3 QueryRunner qr = new QueryRunner(DBUtil.getDruid()); 4 if(qr.update(sql,params)>0) 5 flag = true; 6 return flag; 7 }
還有批量處理形式
/** * 通過預處理解決批量增刪改操作 * * @param sql * @param params params[rows][cols],rows代表sql語句執行次數,cols表示替換占位符的參數個數 * @return boolean * @throws SQLException */ public static boolean batchProcessing(String sql,Object params[][]) throws SQLException{ boolean flag = false; QueryRunner qr = new QueryRunner(DBUtil.getDruid()); if(qr.batch(sql, params).length == params.length) flag = true; return flag; }