Android打造屬於自己的資料庫操作類。

来源:http://www.cnblogs.com/yangqiangyu/archive/2016/05/26/5530440.html
-Advertisement-
Play Games

1、概述 開發Android的同學都知道sdk已經為我們提供了一個SQLiteOpenHelper類來創建和管理SQLite資料庫,通過寫一個子類去繼承它,就可以方便的創建、管理資料庫。但是當我們需要去做增刪改查的操作的時候,就得通過getWritableDatabase獲取一個SQLiteData ...


1、概述

開發Android的同學都知道sdk已經為我們提供了一個SQLiteOpenHelper類來創建和管理SQLite資料庫,通過寫一個子類去繼承它,就可以方便的創建、管理資料庫。但是當我們需要去做增刪改查的操作的時候,就得通過getWritableDatabase獲取一個SQLiteDataBase然後老老實實去寫操作值的put以及查詢返回的Cursor處理,其實我們可以搞一個對象來幫我們乾這些事情,打造屬於你自己的資料庫操作類。

2、操作類的初顯形

假設現在我們什麼都沒有,我們要去搞一個對象來給我們乾這件事情,它需要有什麼才可以乾呢?
先想想要做的事情:管理資料庫的操作
那要做資料庫的操作需要什麼就很簡單了吧?
1、要操作資料庫,所以需要一個SQLiteDataBase對象,可以通過SQLiteOpenHelper的子類來獲取。
2、此外資料庫要創建,還需要資料庫信息吧?那就直接變數引入。
3、有了資料庫信息,創建了資料庫,你要操作,怎麼也得告訴我操作哪個表。所以還得包含創建表和更新表的信息,由於表一般會有多張,所以這裡用一個數組變數。

有了信息還得交互,不然我怎麼知道你要怎麼創建表,所以我們在構造方法中直接獲取這些信息。

接下看上面文字的代碼表示

public abstract class DataBaseHelper {

     /**
     * 用來創建和獲取資料庫的SQLiteOpenHelper
     */
    protected DBHelper mDbHelper;
    /**
     * 資料庫對象
     */
    protected SQLiteDatabase mDb;

    /**
     * 資料庫信息
     */
    private int mDbVersion;//版本
    private String mDbName;//資料庫名
    /**
     * 創建表語句
     */
    private String[] mDbCreateSql;
    /**
     * 更新表語句
     */
    private String[] mDbUpdateSql;

    protected abstract int getMDbVersion(Context context);

    protected abstract String getDbName(Context context);

    protected abstract String[] getDbCreateSql(Context context);

    protected abstract String[] getDbUpdateSql(Context context);

    public DataBaseHelper(Context context) {
        this.mDbVersion = this.getMDbVersion(context);
        this.mDbName = this.getDbName(context);
        this.mDbCreateSql = this.getDbCreateSql(context);
        this.mDbUpdateSql = this.getDbUpdateSql(context);
        this.mDbHelper = new DBHelper(context,this.mDbName,null,this.mDbVersion);
    }

    protected void open(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                mDb = mDbHelper.getWritableDatabase();
            }
        }).start();

    }

    protected SQLiteDatabase getDB(){
        return this.mDb;
    }


    public void close(){
        this.mDb.close();
        this.mDbHelper.close();
    }

    private class DBHelper extends SQLiteOpenHelper{

        public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
            super(context, name, factory, version);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            String[] arr = DataBaseHelper.this.mDbCreateSql;
            //執行創建表語句
            for (int i=0;i<arr.length;i++){
                String sql = arr[i];
                db.execSQL(sql);
            }
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            String[] arr = DataBaseHelper.this.mDbUpdateSql;
             //執行更新語句
            for (int i=0;i<arr.length;i++){
                String sql = arr[i];
                db.execSQL(sql);
            }
        }
    }
}

代碼比較簡單,包含了進行資料庫操作要用到的各種信息,並且在初始化的進行了賦值。同時還提供了SQLiteDatabase的open、close。同時在這裡用到了抽象方法是因為考慮創建多個資料庫的情況,讓子類來提供具體的資料庫信息,我只管做創建和操作就行了。

這裡我們的資料庫操作類已經初顯雛形了,但是現在除了創建表還沒什麼用。操作類不提供簡便的操作還叫什麼操作類,下麵就來說說操作。

我們要做操作類,無非是要簡化操作,就像當老闆一樣。我告訴你一些用到的東西,你去給我完成這個事情。哈哈。

假如我現在就是要操作資料庫的老闆,那我其實只想告訴你必要的事情,其它的我都不想做。

那麼必要的信息只有表名,要操作的欄位和值,如果是刪除、更新、和查詢的話多加個篩選條件。接下來看代碼


 /**
     * 統一對ContentValues處理
     * @param contentValues
     * @param key
     * @param value
     */
    private void ContentValuesPut(ContentValues contentValues,String key,Object value){
        if (value==null){
            contentValues.put(key,"");
        }else{
            String className = value.getClass().getName();
            if (className.equals("java.lang.String")){
                contentValues.put(key,value.toString());
            } else if (className.equals("java.lang.Integer")){
                contentValues.put(key,Integer.valueOf(value.toString()));
            } else if (className.equals("java.lang.Float")){
                contentValues.put(key,Float.valueOf(value.toString()));
            } else if (className.equals("java.lang.Double")){
                contentValues.put(key,Double.valueOf(value.toString()));
            } else if (className.equals("java.lang.Boolean")){
                contentValues.put(key,Boolean.valueOf(value.toString()));
            } else if (className.equals("java.lang.Long")){
                contentValues.put(key,Long.valueOf(value.toString()));
            } else if (className.equals("java.lang.Short")){
                contentValues.put(key,Short.valueOf(value.toString()));
            }
        }
    }

    /**
     * 根據數組的列和值進行insert
     * @param tableName
     * @param columns
     * @param values
     * @return
     */
    public boolean insert(String tableName,String[] columns,Object[] values){
        ContentValues contentValues = new ContentValues();
        for (int rows = 0; rows < columns.length;++rows){
             ContentValuesPut(contentValues,columns[rows],values[rows]);
        }
        long rowId = this.mDb.insert(tableName,null,contentValues);
        return rowId!=-1;
    }

    /**
     * 根據map來進行insert
     * @param tableName
     * @param columnValues
     * @return
     */
    public boolean insert(String tableName,Map<String,Object> columnValues){
        ContentValues contentValues = new ContentValues();
        Iterator iterator = columnValues.keySet().iterator();
        while (iterator.hasNext()){
            String key = (String) iterator.next();
            this.ContentValuesPut(contentValues,key,columnValues.get(key));
        }

        long rowId = this.mDb.insert(tableName,null,contentValues);
        return rowId!=-1;
    }


    /**
     * 統一對數組where條件進行拼接
     * @param whereColumns
     * @return
     */
    private String initWhereSqlFromArray(String[] whereColumns){
        StringBuffer whereStr = new StringBuffer();
        for (int i=0;i<whereColumns.length;++i){
            whereStr.append(whereColumns[i]).append(" = ? ");
            if (i<whereColumns.length-1){
                whereStr.append(" and ");
            }
        }
        return whereStr.toString();
    }

    /**
     * 統一對map的where條件和值進行處理
     * @param whereParams
     * @return
     */
    private Map<String,Object> initWhereSqlFromMap(Map<String,String> whereParams){
        Set set = whereParams.keySet();
        String[] temp = new String[whereParams.size()];
        int i = 0;
        Iterator iterator = set.iterator();
        StringBuffer whereStr = new StringBuffer();
        while (iterator.hasNext()){
            String key = (String) iterator.next();
            whereStr.append(key).append(" = ? ");
            temp[i] = whereParams.get(key);
            if (i<set.size()-1){
                whereStr.append(" and ");
            }
            i++;
        }
        HashMap result = new HashMap();
        result.put("whereSql",whereStr);
        result.put("whereSqlParam",temp);
        return result;
    }


    /**
     * 根據數組條件來update
     * @param tableName
     * @param columns
     * @param values
     * @param whereColumns
     * @param whereArgs
     * @return
     */
    public boolean update(String tableName,String[] columns,Object[] values,String[] whereColumns,String[] whereArgs){
        ContentValues contentValues = new ContentValues();
        for (int i=0;i<columns.length;++i){
            this.ContentValuesPut(contentValues,columns[i],values[i]);
        }
        String whereClause = this.initWhereSqlFromArray(whereColumns);
        int rowNumber = this.mDb.update(tableName,contentValues,whereClause,whereArgs);
        return rowNumber > 0 ;
    }

    /**
     * 根據map值來進行update
     * @param tableName
     * @param columnValues
     * @param whereParam
     * @return
     */
    public boolean update(String tableName,Map<String,Object> columnValues,Map<String,String> whereParam){
        ContentValues contentValues = new ContentValues();
        Iterator iterator = columnValues.keySet().iterator();

        String columns;
        while (iterator.hasNext()){
            columns = (String) iterator.next();
            ContentValuesPut(contentValues,columns,columnValues.get(columns));
        }

        Map map = this.initWhereSqlFromMap(whereParam);
        int rowNumber = this.mDb.update(tableName,contentValues,(String)map.get("whereSql"),(String[]) map.get("whereSqlParam"));
        return rowNumber > 0;
    }

    /**
     * 根據數組條件進行delete
     * @param tableName
     * @param whereColumns
     * @param whereParam
     * @return
     */
    public boolean delete(String tableName,String[] whereColumns,String[] whereParam){
        String whereStr = this.initWhereSqlFromArray(whereColumns);
        int rowNumber = this.mDb.delete(tableName,whereStr,whereParam);
        return rowNumber > 0;
    }


    /**
     * 根據map來進行delete
     * @param tableName
     * @param whereParams
     * @return
     */
    public boolean delete(String tableName,Map<String,String> whereParams){
        Map map = this.initWhereSqlFromMap(whereParams);
        int rowNumber = this.mDb.delete(tableName,map.get("whereSql").toString(),(String[]) map.get("whereSqlParam"));
        return rowNumber > 0;
    }


    /**
     * 查詢返回List
     * @param sql
     * @param params
     * @return
     */
    public List<Map> queryListMap(String sql,String[] params){
        ArrayList list = new ArrayList();
        Cursor cursor = this.mDb.rawQuery(sql,params);
        int columnCount = cursor.getColumnCount();
        while (cursor.moveToNext()){
            HashMap item = new HashMap();
            for (int i=0;i<columnCount;++i){
                int type = cursor.getType(i);
                switch (type){
                    case 0:
                        item.put(cursor.getColumnName(i),null);
                        break;
                    case 1:
                        item.put(cursor.getColumnName(i), cursor.getInt(i));
                        break;
                    case 2:
                        item.put(cursor.getColumnName(i),cursor.getFloat(i));
                        break;
                    case 3:
                        item.put(cursor.getColumnName(i),cursor.getString(i));
                        break;
                }
            }
            list.add(item);
        }
        cursor.close();
        return list;
    }

    /**
     * 查詢單條數據返回map
     * @param sql
     * @param params
     * @return
     */
    public Map queryItemMap(String sql,String[] params){
        Cursor cursor = this.mDb.rawQuery(sql,params);
        HashMap map = new HashMap();
        if (cursor.moveToNext()){
            for (int i = 0;i < cursor.getColumnCount();++i){
                int type = cursor.getType(i);
                switch (type){
                    case 0:
                        map.put(cursor.getColumnName(i),null);
                        break;
                    case 1:
                        map.put(cursor.getColumnName(i),cursor.getInt(i));
                        break;
                    case 2:
                        map.put(cursor.getColumnName(i),cursor.getFloat(i));
                        break;
                    case 3:
                        map.put(cursor.getColumnName(i),cursor.getString(i));
                        break;
                }
            }
        }
        cursor.close();
        return map;
    }

    public void execSQL(String sql){
        this.mDb.execSQL(sql);
    }

    public void execSQL(String sql,Object[] params){
        this.mDb.execSQL(sql,params);
    }

上面的操作代碼就完畢了,這裡主要對增刪改的參數是數組和Map的情況進行了處理,對查詢的結果進行了處理,代碼比較簡單也都有註釋,這裡就不做特別說明瞭。到這裡一個資料庫操作類就成型了。

3、操作類的繼續完善

通過上面的過程已經可以使用了,那麼先來看看使用,我們只需要繼承操作抽象類告訴它具體的資料庫信息以及建表語句。

public class TestDBHelper extends DataBaseHelper {

    private static TestDBHelper mTestDBHelper;

    private TestDBHelper(Context context){
        super(context);
    }

    public static TestDBHelper getInstance(Context context){
        if (mTestDBHelper==null){
            synchronized (DataBaseHelper.class){
                if (mTestDBHelper==null){
                    mTestDBHelper = new TestDBHelper(context);
                    if (mTestDBHelper.getDB()==null||!mTestDBHelper.getDB().isOpen()){
                        mTestDBHelper.open();
                    }
                }
            }
        }
        return mTestDBHelper;
    }

    @Override
    protected int getMDbVersion(Context context) {
        return 1;
    }

    @Override
    protected String getDbName(Context context) {
        return "test.db";
    }

    @Override
    protected String[] getDbCreateSql(Context context) {
        String[] a = new String[1];
        a[0] = "CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,gender TEXT,age INTEGER)";
        return a;
    }

    @Override
    protected String[] getDbUpdateSql(Context context) {
        return new String[0];
    }
}

重寫父類的抽象方法告訴它資料庫信息以及建表語句,然後提供一個單例供外部獲取,如果沒有open就open資料庫,接下來看看使用

4、使用

直接獲取,然後傳入你想操作的表信息,So Easy!

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button selectBtn;
    private Button insertBtn;
    private Button updateBtn;
    private Button deleteBtn;
    private TextView contentTv;

    private TestDBHelper testDBHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        testDBHelper = TestDBHelper.getInstance(getApplicationContext());

        selectBtn = (Button) findViewById(R.id.select_btn);
        insertBtn = (Button) findViewById(R.id.insert_btn);
        updateBtn = (Button) findViewById(R.id.update_btn);
        deleteBtn = (Button) findViewById(R.id.delete_bt);
        contentTv = (TextView) findViewById(R.id.content_tv);


        selectBtn.setOnClickListener(this);
        insertBtn.setOnClickListener(this);
        updateBtn.setOnClickListener(this);
        deleteBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.select_btn:
                List<Map> list = testDBHelper.queryListMap("select * from user",null);
                contentTv.setText(String.valueOf(list));
                break;
            case R.id.insert_btn:
                testDBHelper.insert("user",new String[]{"name","gender","age"},new Object[]{"qiangyu","male",23});
                break;
            case R.id.update_btn:
                testDBHelper.update("user",new String[]{"name","gender","age"},new Object[]{"yangqiangyu","male",24},
                        new String[]{"name"},new String[]{"qiangyu"});
                break;
            case R.id.delete_bt:
                testDBHelper.delete("user",
                        new String[]{"name"},new String[]{"qiangyu"});
                break;
        }
    }
}

很簡單了,附一張演示圖
gif製作了做了壓縮,圖的效果不好請見諒
這裡寫圖片描述

是不是簡單多了

**yissan的博客,未經允許嚴禁轉載 http://blog.csdn.net/yissan**

5、最後的完善

在第3步里,我們的資料庫信息,和建表語句都是寫在具體的代碼里的,這樣我們每次修改都要動代碼。Android推薦我們這些具體的信息都寫在配置文件xml裡面,那麼我們就來做一下修改。

建立一個db.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <array name="DATABASE_INFO">
        <item>test.db</item>
        <item>1</item>
    </array>

    <array name="CREATE_TABLE_SQL">
        <item>CREATE TABLE user (id INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,gender TEXT,age INTEGER)</item>
    </array>

    <array name="UPDATE_TABLE_SQL">
        <item></item>
    </array>

</resources>

現在的獲取數據信息的代碼是這樣

 @Override
    protected int getMDbVersion(Context context) {
        return Integer.valueOf(context.getResources().getStringArray(R.array.DATABASE_INFO)[1]);
    }

    @Override
    protected String getDbName(Context context) {
        return context.getResources().getStringArray(R.array.DATABASE_INFO)[0];
    }

    @Override
    protected String[] getDbCreateSql(Context context) {
        return context.getResources().getStringArray(R.array.CREATE_TABLE_SQL);
    }

    @Override
    protected String[] getDbUpdateSql(Context context) {
        return context.getResources().getStringArray(R.array.UPDATE_TABLE_SQL);
    }

從配置文件當中獲取資料庫信息,這樣以後每次修改只需要修改xml文件就可以了。

6、結語

到此,一個資料庫操作類就完成啦,當然你可以根據自己的需要在其實添加更多的便捷操作方法。

這裡提供的操作類,在使用的時候我們還在需要在Activity中寫一些查詢的sql代碼,我們可以再搞一個統一做各種具體操作表的對象。

覺得不錯別忘記點贊喲!

最後送給大家一個雞湯,共勉

他每做一件小事的時候 他都像救命稻草一樣抓著 有一天我一看 嚯 好家伙 他抱著的是已經是讓我仰望的參天大樹


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • BaseControl按鈕合集 效果 源碼 https://github.com/YouXianMing/Animations 說明 本人一共封裝了3種按鈕的基類控制項,以上是一個示例演示,演示如何通過繼承來實現想要的效果. ...
  • Most tools require installation on your computer before you can use them. If the installation is easy, you may think that’s fine. But it can be an unn ...
  • 蘋果的規定:2016年6月1日提交到App Store必須支持IPv6-only網路。 官方說明:https://developer.apple.com/library/mac/documentation/NetworkingInternetWeb/Conceptual/NetworkingOver ...
  • ARC 和 MRC 記憶體管理 從 MRC—>ARC 就是將記憶體管理部分,從開發者的函數中轉移到函數外部的runtime 中.由於 runtime 的開發簡單,邏輯層次高,所以 runtime 的出錯幾率很小,另外由於編譯器的優化,使得運行速度很高. ARC 的特點: 不能顯示的調用 dealloc, ...
  • 報錯一: 在iOS7的真機運行時,彈出錯誤:App installation failed. There was an internal API error. 如圖 解決辦法: 在Xcode -> Target -> Build Setting 下的Packaging部分,將Product Name ...
  • 1 什麼是 OC 語言? OC 語言即面向對象語言,它擴展了 ANSI C 語言,將 SmallTalk 式的消息傳遞機制加入到 ANSI C 中.它是蘋果 OS 和 iOS 以及相關的 API,Cocoa 和 Cocoa Touch 的主要編程語言. 2 OC 語言的特點: 支持 C 語言語法,是 ...
  • 今天建立android4.3模擬器的時候發現沒有android4.3 Intel X86 Atom System Image可選,打開android SDK Manager 於是希望重現選擇下載安裝,但是時間等得太久,都沒與出現可以下載安裝的按鈕 於是從下麵的網址選擇相應的版本驚進行安裝: http ...
  • 在圖示位置把提示的東西加上即可 參考: iOS app with framework crashed on device, dyld: Library not loaded, Xcode 6 Beta 但是當歸檔完成導出ipa文件時會提示"Found an unexpected Mach-O hea ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...