Android架构设计01-数据库框架

作者: Androidgiao | 来源:发表于2019-08-05 15:10 被阅读5次
    涉及到数据库的操作一般的都是使用第三方的框架,如GreeoDao,OrmLitem等。或者是直接利用SQLiteOpenHelper来完成数据库的增删改查以及数据库升级。那么对于这种写法,一般都比较繁琐。操作如下:
    DBHelper dbHelper = new DBHelper(this);
    SQLiteDatabase sqLiteDatabase = dbHelper.getWritableDatabase();
    sqLiteDatabase.execSQL("create table if not exists tb_weichat(name varchar(20),password varchar(10))");
    ContentValues contentValues  = new ContentValues();
    contentValues.put("user_name","张三");
    contentValues.put("password","123456");
    sqLiteDatabase.beginTransaction();
    int scheduleID = -1;
    dbHelper.insert("schedule",null,values);
    dbHelper.setTransctionSuccessful();
    

    使用框架实现

    User user = new User("张三", "20122425");
    baseDao.insert(user);
    

    `可以看出使用框架和之前相比省了很多行代码。操作更简单。

    用到的知识点

    泛型
    注解
    反射
    数据库语句拼接

    用到的设计的模式
    单例模式
    简单工厂模式
    模板方法模式

    3类图

    20170410135820276.png

    4 具体实现

    IBaseDao

    public interface IBaseDao<T> {
        /**
         * 数据库插入操作
         * @param entity
         * @return
         */
        Long insert(T entity);
    
        /**
         * 数据库删除
         * @param where
         * @return
         */
        int delete(T where);
    
        /**
         * 数据库更改操作
         * @param entity
         * @param where
         * @return
         */
        int updata(T entity,T where);
    
        /**
         * 数据库查询操作
         * @param where
         * @return
         */
        List<T> query(T where);
    
    }
    

    这个借口约束了数据库行为,数据库中有增删改查功能。

    BaseDao

    public abstract class BaseDao<T> implements IBaseDao<T> {
    
        //只能初始化一次
        private boolean isInit = false;
    
        //被插入数据库的实体
        private Class<T> mEntityClass;
    
        private SQLiteDatabase mSqLiteDatabase;
    
        //表名
        private String tableName;
    
        /**
         * 用来维护表与实体的对应关系
         * key:   表的列名
         * value: entity的Field名
         */
        private HashMap<String, Field> cacheMap;
    
        /**
         * @param entityClass    要出入数据库的实体类
         * @param sqLiteDatabase 数据库管理的对象
         */
        public synchronized boolean init(Class<T> entityClass, SQLiteDatabase sqLiteDatabase) {
            if (!isInit) {
                mEntityClass = entityClass;
                mSqLiteDatabase = sqLiteDatabase;
    
                if (mEntityClass.getAnnotation(DbTable.class) != null) {
                    //注解DbTable的值为表名
                    tableName = entityClass.getAnnotation(DbTable.class).value();
                } else {
                    //如果没有注解,对应的类名为表名
                    tableName = entityClass.getSimpleName();
                }
    
                //创建表
                if (!TextUtils.isEmpty(createTable())) {
                    sqLiteDatabase.execSQL(createTable());
                }
    
                cacheMap = new HashMap<>();
                initCacheMap();
                isInit = true;
            }
            return isInit;
        }
    
        /**
         * 初始化cacheMap,
         * 将表的列明和对应的entity的成员变量名字赋值给该cacheMap
         */
    
        private void initCacheMap() {
            String sql = "select * from " + this.tableName + " limit 1,0";
            Cursor cursor = null;
            try {
    
    
                cursor = mSqLiteDatabase.rawQuery(sql, null);
    
                //表的列名数组
                String[] columnsName = cursor.getColumnNames();
    
                //entitiy的Field数组
                Field[] fields = mEntityClass.getFields();
    
                //防止私有属性无法访问
                for (Field field : fields) {
                    field.setAccessible(true);
                }
    
                //遍历列名
                for (String columnName : columnsName) {
                    //遍历成员变量
                    for (Field field : fields) {
                        String fieldName = null;
                        if (field.getAnnotation(DbField.class) != null) {
                            fieldName = field.getAnnotation(DbField.class).value();
                        } else {
                            fieldName = field.getName();
                        }
    
                        if (field != null && columnName.equals(fieldName)) {
                            cacheMap.put(columnName, field);
                            break;
                        }
    
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (null != cursor) {
                    cursor.close();
                }
            }
        }
    
        //=============================================插入
        @Override
        public Long insert(T entity) {
            Map<String, String> map = getValue(entity);
            ContentValues contentValues = getContentValues(map);
            Long reslt = mSqLiteDatabase.insert(tableName, null, contentValues);
            return reslt;
        }
    
        //=============================================删除
        @Override
        public int delete(T where) {
            int result = -1;
    
            Map whereClause = getValue(where);
            Condition condition = new Condition(whereClause);
    
            result = mSqLiteDatabase.delete(tableName, condition.getWhereClause(), condition.getWhereArgs());
            return result;
        }
    
        //=============================================更新
        @Override
        public int updata(T entity, T where) {
            int result = -1;
            Map whereClause = getValue(where);
            Map values = getValue(entity);
    
            Condition condition = new Condition(whereClause);
            ContentValues contentValues = getContentValues(values);
    
            result = mSqLiteDatabase.update(tableName, contentValues, condition.getWhereClause(), condition.getWhereArgs());
            return result;
        }
    
        //=============================================更新
        @Override
        public List<T> query(T where) {
    
            return query(where, null, null, null);
        }
    
        private List<T> query(T where, String orderBy, Integer startIndex, Integer limit) {
            Map map = getValue(where);
            String limitString = null;
            if (startIndex != null && limit != null) {
                limitString = startIndex + " , " + limit;
            }
    
            Condition condition = new Condition(map);
            Cursor cursor = mSqLiteDatabase.query(tableName, null, condition.getWhereClause(), condition.getWhereArgs(), null, null, orderBy, limitString);
    
            List<T> result = getResult(where, cursor);
            cursor.close();
            return result;
        }
    
        /**
         * 将查询的结果返回
         * @param where  表中每条数据对应的实体类
         * @param cursor  查询结果返回的cursor对象
         * @return  返回所有的查询结果
         */
        protected List<T> getResult(T where, Cursor cursor) {
            ArrayList list = new ArrayList();
            Object item;
            //先遍历表中的所有行
            while (cursor.moveToNext()) {
                try {
                    //根据一行 创建一个实例
                    item = where.getClass().newInstance();
                    Iterator iterator = cacheMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry entry = (Map.Entry) iterator.next();
    
                        //得到列名
                        String columnName = (String) entry.getKey();
    
                        //根据列名 得出列的位置
                        Integer columnIndex = cursor.getColumnIndex(columnName);
    
                        Field field = (Field) entry.getValue();
    
                        //获取Field的类型
                        Class type = field.getType();
    
                        //判断Field的类型
                        if (columnIndex != -1) {
                            if (type == String.class) {
                                //根据反射进行赋值
                                field.set(item, cursor.getString(columnIndex));
                            } else if (type == Double.class) {
                                field.set(item, cursor.getDouble(columnIndex));
                            } else if (type == Integer.class) {
                                field.set(item, cursor.getInt(columnIndex));
                            } else if (type == Long.class) {
                                field.set(item, cursor.getLong(columnIndex));
                            } else if (type == Byte.class) {
                                field.set(item, cursor.getBlob(columnIndex));
                                //不支持类型
                            } else {
                                continue;
                            }
                        }
                    }
    
                    list.add(item);
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return list;
        }
    
        ;
    
        /**
         * 把map转成contentValues
         * key:列名   value:Field值
         *
         * @param map
         * @return
         */
        private ContentValues getContentValues(Map<String, String> map) {
            ContentValues contentValues = new ContentValues();
    
            Set keys = map.keySet();
            Iterator<String> iterator = keys.iterator();
    
            while (iterator.hasNext()) {
                String columnName = iterator.next();
                String value = map.get(columnName);
    
                if (!TextUtils.isEmpty(columnName) && !TextUtils.isEmpty(value)) {
                    contentValues.put(columnName, value);
                }
    
            }
            return contentValues;
        }
    
        ;
    
    
        /**
         * 用map 来存储entity的属性值 key为对应属性的注解值
         * key:"user_name"   vlaue:"张三"
         *
         * @param entity
         * @return
         */
        private Map<String, String> getValue(T entity) {
            Map<String, String> map = new HashMap<>();
            Iterator<Field> fieldIterator = cacheMap.values().iterator();
    
            while (fieldIterator.hasNext()) {
                Field field = fieldIterator.next();
    
                String key = null; //列名
                String value = null; //field值
    
                if (field.getAnnotation(DbField.class) != null) {
                    key = field.getAnnotation(DbField.class).value();
                } else {
                    key = field.getName();
                }
    
                try {
                    if (field.get(entity) == null) {
                        continue;
                    }
                    value = field.get(entity).toString();
                    if (value != null) {
                        map.put(key, value);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
    
            }
            return map;
        }
    
        class Condition {
            /**
             * 条件语句
             * name=?&&password=?
             */
            private String whereClause;
    
            private String[] whereArgs;
    
            public Condition(Map<String, String> whereClause) {
                ArrayList list = new ArrayList();
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(" 1=1 ");
    
    
                Set keySet = whereClause.keySet();
                Iterator<String> iterator = keySet.iterator();
                while (iterator.hasNext()) {
                    String key = iterator.next();
                    String value = whereClause.get(key);
                    if (key != null) {
    
                        //拼接条件语句  1=1 and name =? and password =?
                        stringBuilder.append(" and " + key + " =?");
    
                        list.add(value);
                    }
                }
    
                this.whereClause = stringBuilder.toString();
                this.whereArgs = (String[]) list.toArray(new String[list.size()]);
            }
    
            public String getWhereClause() {
                return whereClause;
            }
    
            public String[] getWhereArgs() {
                return whereArgs;
            }
        }
    
    
        /**
         * 每个Dao的建的表各不相同,所以此方法留给子类实现
         *
         * @return 建表的字符串语句
         */
        public abstract String createTable();
    }
    

    这个方法做了这几件事情:

    初始化每一条数据对应的实体类。

      mEntityClass = entityClass;
    

    初始化SQLiteDataBase对象

    mSqLiteDatabase = sqLiteDatabase;
    

    初始化表名

    if (mEntityClass.getAnnotation(DbTable.class) != null) {
                    //注解DbTable的值为表名
                    tableName = entityClass.getAnnotation(DbTable.class).value();
                } else {
                    //如果没有注解,对应的类名为表名
                    tableName = entityClass.getSimpleName();
                }
    

    创建表 这里的createTalbe方法是抽象方法,也是BaseDao子类唯一需要重写的方法。也就是说BaseDao的子类除了建表语句不同之外,其他的方法都是一样的。

     if (!TextUtils.isEmpty(createTable())) {
                    sqLiteDatabase.execSQL(createTable());
                }
    

    初始化cacheMap

    cacheMap = new HashMap<>();
                initCacheMap();

    相关文章

      网友评论

        本文标题:Android架构设计01-数据库框架

        本文链接:https://www.haomeiwen.com/subject/lacmdctx.html