Android打造屬於本身的數據庫操做類。

一、概述

開發Android的同窗都知道sdk已經爲咱們提供了一個SQLiteOpenHelper類來建立和管理SQLite數據庫,經過寫一個子類去繼承它,就能夠方便的建立、管理數據庫。可是當咱們須要去作增刪改查的操做的時候,就得經過getWritableDatabase獲取一個SQLiteDataBase而後老老實實去寫操做值的put以及查詢返回的Cursor處理,其實咱們能夠搞一個對象來幫咱們幹這些事情,打造屬於你本身的數據庫操做類。java

二、操做類的初顯形

假設如今咱們什麼都沒有,咱們要去搞一個對象來給咱們幹這件事情,它須要有什麼才能夠幹呢?
先想一想要作的事情:管理數據庫的操做
那要作數據庫的操做須要什麼就很簡單了吧?
一、要操做數據庫,因此須要一個SQLiteDataBase對象,能夠經過SQLiteOpenHelper的子類來獲取。
二、此外數據庫要建立,還須要數據庫信息吧?那就直接變量引入。
三、有了數據庫信息,建立了數據庫,你要操做,怎麼也得告訴我操做哪一個表。因此還得包含建立表和更新表的信息,因爲表通常會有多張,因此這裏用一個數組變量。sql

有了信息還得交互,否則我怎麼知道你要怎麼建立表,因此咱們在構造方法中直接獲取這些信息。數據庫

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

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。同時在這裏用到了抽象方法是由於考慮建立多個數據庫的狀況,讓子類來提供具體的數據庫信息,我只管作建立和操做就好了。app

這裏咱們的數據庫操做類已經初顯雛形了,可是如今除了建立表還沒什麼用。操做類不提供簡便的操做還叫什麼操做類,下面就來講說操做。ide

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

假如我如今就是要操做數據庫的老闆,那我其實只想告訴你必要的事情,其它的我都不想作。.net

那麼必要的信息只有表名,要操做的字段和值,若是是刪除、更新、和查詢的話多加個篩選條件。接下來看代碼code

/**
     * 統一對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的狀況進行了處理,對查詢的結果進行了處理,代碼比較簡單也都有註釋,這裏就不作特別說明了。到這裏一個數據庫操做類就成型了。xml

三、操做類的繼續完善

經過上面的過程已經可使用了,那麼先來看看使用,咱們只須要繼承操做抽象類告訴它具體的數據庫信息以及建表語句。

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數據庫,接下來看看使用

四、使用

直接獲取,而後傳入你想操做的表信息,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

五、最後的完善

在第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文件就能夠了。

六、結語

到此,一個數據庫操做類就完成啦,固然你能夠根據本身的須要在其實添加更多的便捷操做方法。

這裏提供的操做類,在使用的時候咱們還在須要在Activity中寫一些查詢的sql代碼,咱們能夠再搞一個統一作各類具體操做表的對象。

以爲不錯別忘記點贊喲!

最後送給你們一個雞湯,共勉

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

相關文章
相關標籤/搜索