zoukankan      html  css  js  c++  java
  • Android打造属于自己的数据库操作类。

    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代码,我们可以再搞一个统一做各种具体操作表的对象。

    觉得不错别忘记点赞哟!

    最后送给大家一个鸡汤,共勉

    他每做一件小事的时候 他都像救命稻草一样抓着 有一天我一看 嚯 好家伙 他抱着的是已经是让我仰望的参天大树

  • 相关阅读:
    描述网络的优点与缺点
    外键之表格三种关系
    Mysql完整性约束
    Mysql数据类型
    mysql的基本语句
    Mysql的基本安装
    type与object的关系
    反射
    面向对象内置方法(进阶)
    Python 的五种io模型理解
  • 原文地址:https://www.cnblogs.com/yangqiangyu/p/5530440.html
Copyright © 2011-2022 走看看