標籤:android 應用開發 源碼 資料庫
任何android應用程式都少不了資料庫的操作,即使是用戶端程式也會有一些特定的資料存入到資料庫中,例如:使用者瀏覽記錄,收藏列表等等,所以資料庫的操作就是一個會很頻繁使用的操作,所以對這個部分的封裝就很有必要了,Web端有Hibernate等一系列優秀的架構,雖然android應用程式在git上也有一些開源的OOM架構,但總覺得還是沒必要引入第三方的東西,於是就自己封裝了一個資料庫操作類,只要調用此類相應的方法,傳入要儲存的實體物件或更新的實體物件即可,查詢也是同樣的,只要傳入查詢條件和Class,就返回對應的實體物件,這樣只要我們進行一次封裝,以後就可以直接用這個類去操作資料庫,而不必每次都寫繁雜的sql語句.下面就是我封裝類的部分代碼:
import com.micen.buyers.module.db.Module;/********************************************************** * @檔案名稱:DBDataHelper.java * @建立時間:2014-2-10 下午02:41:51 * @檔案描述:資料庫操作助手類 * @修改曆史:2014-2-10建立初始版本 **********************************************************/public final class DBDataHelper{private static DBDataHelper dataHelper = null;private DBHelper dbHelper = null;private static final String SELECT = "select ";private static final String FROM = " from ";private static final String WHERE = " where ";private static final String ORDER_BY = " order by ";private DBDataHelper(){dbHelper = DBHelper.getInstance();}public static DBDataHelper getInstance(){if (dataHelper == null){dataHelper = new DBDataHelper();}return dataHelper;}/** * 根據條件查詢資料庫表 * @param tableName * @param showColumns * @param selection * @param selectionArgs * @param orderBy * @param cls * @return */public ArrayList<Module> select(String tableName, String showColumns, String selection, String selectionArgs,String orderBy, Class<?> cls){synchronized (dbHelper){ArrayList<Module> moduleList = new ArrayList<Module>();SQLiteDatabase db = null;try{db = dbHelper.getReadableDatabase();String sql = SELECT;sql += showColumns != null ? showColumns : "*";sql += FROM + tableName;if (selection != null && selectionArgs != null){sql += WHERE + selection + " = " + selectionArgs;}if (orderBy != null){sql += ORDER_BY + orderBy;}Cursor cursor = db.rawQuery(sql, null);changeToList(cursor, moduleList, cls);}catch (Exception e){e.printStackTrace();}finally{dbHelper.closeDatabase(db);}return moduleList;}}/** * 尋找資料表 * * @param table * 要操作的表 * @param selection * 匹配條件,例如"id>?and name <>?",不需要可以設為null * @param selectionArgs * 與selection相對應,裡面的字串將替換selection裡的"?", * 構成完整的匹配條件,例如{"6","jack"} * @param orderby 排序參數 * @param moduleClass * 要轉化成的模型類Class,例如要轉成WebPage則傳入WebPage.class * @return 資料模型集合,集合是的物件類型為moduleClass */public ArrayList<Module> select(final String table, final String selection, final String[] selectionArgs,final String orderby, final Class<?> moduleClass){SQLiteDatabase database = null;Cursor cursor = null;ArrayList<Module> moduleList = new ArrayList<Module>();synchronized (dbHelper){try{database = dbHelper.getReadableDatabase();// 查詢資料cursor = database.query(table, null, selection, selectionArgs, null, null, orderby, null);// 將結果轉換成為資料模型changeToList(cursor, moduleList, moduleClass);}catch (Exception e){e.printStackTrace();}finally{dbHelper.closeDatabase(database);}return moduleList;}}private void changeToList(Cursor cursor, List<Module> modules, Class<?> moduleClass){// 取出所有的列名int count = cursor.getCount();Module module;cursor.moveToFirst();synchronized (dbHelper){try{// 遍曆遊標for (int i = 0; i < count; i++){// 轉化為moduleClass類的一個執行個體module = changeToModule(cursor, moduleClass);modules.add(module);cursor.moveToNext();}}catch (SecurityException e){// Log.e(TAG, e + FusionCode.EMPTY_STRING);}catch (IllegalArgumentException e){// Log.e(TAG, e + FusionCode.EMPTY_STRING);}catch (IllegalAccessException e){// Log.e(TAG, e + FusionCode.EMPTY_STRING);}catch (InstantiationException e){// Log.e(TAG, e + FusionCode.EMPTY_STRING);}catch (NoSuchFieldException e){System.out.println("");}finally{cursor.close();}}}private Module changeToModule(Cursor cursor, Class<?> moduleClass) throws IllegalAccessException,InstantiationException, SecurityException, NoSuchFieldException{synchronized (dbHelper){// 取出所有的列名String[] columnNames = cursor.getColumnNames();String filedValue;int columncount = columnNames.length;Field field;Module module = (Module) moduleClass.newInstance();// 遍曆有列for (int j = 0; j < columncount; j++){// 根據列名找到相對應 的欄位field = moduleClass.getField(columnNames[j]);filedValue = cursor.getString(j);if (filedValue != null){field.set(module, filedValue.trim());}}return module;}}/** * 向資料庫插入資料 * * @param table * 要操作的表 * @param module * 資料模型,id設為自增,若沒指定,則自動產生;若指定則插入指定的id, * 但是在資料表已存在該id的情況下會導致插入失敗,建議不指定id * @return 插入行的行號,可以看作是id */public long insert(final String table, final Module module){synchronized (dbHelper){ContentValues values = moduleToContentValues(module);return dbHelper.insert(table, null, values);}}/** * 向資料庫更新資料 * * @param table * 要操作的表 * @param module * @return 更新行的行號,可以看作是id */public long update(final String table, final Module module){synchronized (dbHelper){ContentValues values = moduleToContentValues(module);return dbHelper.update(table, values, DBHelper.ID + "=?", new String[]{ module.id });}}/** * 刪除一條資料記錄 * * @param table * 要操作的表 * @param module * 資料模型,該操作是根據id刪除的,若id為null或不正確是不能成功刪除的 * @return 資料表受影響的行數,0或1 */public int delete(final String table, final Module module){synchronized (dbHelper){return dbHelper.delete(table, "id=?", new String[]{ module.id });}}/** * 刪除資料 * * @param table * 要操作的表 * @param whereClause * 匹配條件,例如"id>?and name <>?",合格記錄將被刪除, * 不需要可以設為null,這樣整張表的內容都會被刪除 * @param whereArgs * 與selection相對應,裡面的字串將替換selection裡的"?", * 構成完整的匹配條件,例如{"6","jack"} * @return 資料表受影響的行數 */public int delete(final String table, final String whereClause, final String[] whereArgs){synchronized (dbHelper){return dbHelper.delete(table, whereClause, whereArgs);}}/** * 將Module類型轉成ContentValues * * @param module * 源Module * @return ContentValues * @author shenghua.lin */private ContentValues moduleToContentValues(final Module module){ ContentValues values = new ContentValues(); Field[] fields = module.getClass().getFields(); String fieldName; String fieldValue; int fieldValueForInt = -1;try{for (Field field : fields){fieldName = field.getName();if (field.get(module) instanceof String){fieldValue = (String) field.get(module);if (fieldValue != null){values.put(fieldName, fieldValue.trim());}else{values.put(fieldName, "");}}else if (field.get(module) instanceof Integer){fieldValueForInt = (Integer) field.get(module);if (fieldValueForInt != -1){values.put(fieldName, fieldValueForInt);}}}}catch (IllegalArgumentException e){}catch (IllegalAccessException e){}return values;}}
思路: 對Sqlite的CRUD操作,其實就是實體類與android ContentValues的相互轉化,那麼我們通過反射,是可以做到兩種類間的相互轉化的,也就可以實現ORM映射了.避免了引入第三方庫的學習成本.
android Sqlite操作之-- 自訂ORM關係實體映射類