中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android架構中的數據庫框架該如何搭建

發布時間:2021-09-24 17:43:25 來源:億速云 閱讀:148 作者:柒染 欄目:開發技術

這篇文章將為大家詳細講解有關Android架構中的數據庫框架該如何搭建,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

    前言:

    你還在苦惱的寫SQL么?你還在為數據庫升級而煩惱么?你還在因查詢數據而寫繁瑣不可用的代碼么? 在這,這些都將不復存在!在本篇中,將會讓你一點一滴從無到有創建一個不再為數據庫而煩惱的框架。

    在開始之前我們先欣賞一下本章實現的最終效果 效果展示 Android架構中的數據庫框架該如何搭建

     如圖所示:

    • 對應的model,可直接成為表結構,不再寫對應的 Create table xxx對應的SQL了

    • 對應model的Dao層,里面封裝了數據表的基本操作(增刪改查)

    • 對應的增刪改查操作,再也不用SQL了,全用對象處理

    接下來開始實戰了

    1、先創建對應相關操作的注解

    1.1 bTable 標識表

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DbTable {
     //表名
        String value();
    }

    1.2 DbPrimaryKey 標識主鍵

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DbPrimaryKey {
        
        //表列名
        String value();
    
        //是否為自動增長
        boolean isAuto() default false;
    }

    1.3 DbFiled 標識成員屬性

    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DbFiled {
     
     //表列名
        String value();
        /*
     這里可以像主鍵一樣,添加其他屬性,比如是否唯一約束,是否非空等
     甚至可以將主鍵的約束放在這里來,只是表明可以這樣做,具體怎樣擴展,完全可以按你們想法來
     */
    }

    2、創建對應表操作類Dao層

    2.1 建 待實現的基層 IBaseDao

    public interface IBaseDao<T> {
    
        Long insert(T entity);
    
        int update(T entity, T where);
    
        /**
         * 刪除數據
         *
         * @param where
         * @return
         */
        int delete(T where);
    
    
        /**
         * 查詢數據
         */
        List<T> query(T where);
    
        List<T> query(T where, String groupBy, String orderBy, String having, Integer startIndex,
                      Integer limit);
    }

    代碼分析:

    這里創建了基類 IBaseDao ,擁有待實現的增刪改查, T 代表對應的 數據表結構的 model

    2.2 建已實現的基層 BaseDao

    public class BaseDao<T> implements IBaseDao<T> {
    
        private static final String TAG = "hqk";
    
        /**
         * 持有數據庫操作類的引用
         */
        private SQLiteDatabase database;
        /**
         * 持有操作數據庫表所對應的java類型
         * User
         */
        private Class<T> entityClass;
        /**
         * 保證實例化一次
         */
        private boolean isInit = false;
    
        private String tableName;
    
        //    檢查表
        private HashMap<String, Field> cacheMap;
    
        protected BaseDao() {
        }
    
        protected synchronized boolean init(Class<T> entity, SQLiteDatabase sqLiteDatabase) {
            if (!isInit) {
                //初始化完了  自動建表
                entityClass = entity;
                database = sqLiteDatabase;
                if (entity.getAnnotation(DbTable.class) == null) {
                    tableName = entity.getClass().getSimpleName();
                } else {
                    tableName = entity.getAnnotation(DbTable.class).value();
                }
                if (!database.isOpen()) {
                    return false;
                }
                String sql = createTable();
                database.execSQL(sql);
                //建立好映射關系
                initCacheMap();
                isInit = true;
            }
            return true;
        }
    
        /**
         * 將真實表中的列名  + 成員變量進行 映射
         * 緩存對應的 表 Model里的屬性名以及對應表列名
         */
        private void initCacheMap() {
            cacheMap = new HashMap<>();
            //這里沒有必要查詢 對應表中的任何數據,只想要對應表列名,所以 這 limit 0
            String sql = "select * from " + tableName + " limit 0";
            Cursor cursor = database.rawQuery(sql, null);
            String[] columnNames = cursor.getColumnNames();
            Field[] columnFields = entityClass.getDeclaredFields();
            //獲取對應表中的列名數組,以及對應表Model里面的屬性數組
            for (String columnName : columnNames) {
                Field resultField = null;
                for (Field field : columnFields) {
                    //拿到對應屬性的注解值
                    String fieldAnnotationName = field.getAnnotation(DbFiled.class).value();
                    //如果對應的屬性注解值與數據庫表列名相同,則拿到對應屬性值
                    if (columnName.equals(fieldAnnotationName)) {
                        resultField = field;
                        break;
                    }
                }
                if (resultField != null) {
                    cacheMap.put(columnName, resultField);
                }
            }
    
        }
    
        /**
         * 組裝 創建表的SQL語句
         *
         * @return
         */
        private String createTable() {
            StringBuffer stringBuffer = new StringBuffer();
            //開始組裝 SQL語句
            stringBuffer.append("create table if not exists ");
            stringBuffer.append(tableName + " (");
            Field[] fields = entityClass.getDeclaredFields();
            for (Field field : fields) {
                Class type = field.getType();
                String primaryKey = null;
                try {
                    primaryKey = field.getAnnotation(DbPrimaryKey.class).value();
                } catch (Exception e) {
    
                }
                Log.i(TAG, "createTable primaryKey " + primaryKey);
                Log.i(TAG, "createTable type " + type);
                if (type == String.class) {
                    if (null == primaryKey) {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " TEXT,");
                    } else {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " TEXT PRIMARY KEY,");
                    }
                } else if (type == Double.class) {
                    if (null == primaryKey) {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  DOUBLE,");
                    } else {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  DOUBLE PRIMARY KEY,");
                    }
                } else if (type == Integer.class) {
                    if (null == primaryKey) {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  INTEGER,");
                    } else {
                        boolean isAuto = field.getAnnotation(DbPrimaryKey.class).isAuto();
                        if (isAuto) {
                            stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  INTEGER PRIMARY KEY AUTOINCREMENT,");
                        } else {
                            stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  INTEGER PRIMARY KEY,");
                        }
                    }
                } else if (type == Long.class) {
                    if (null == primaryKey) {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  BIGINT,");
                    } else {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  BIGINT PRIMARY KEY,");
                    }
                } else if (type == byte[].class) {
                    if (null == primaryKey) {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  BLOB,");
                    } else {
                        stringBuffer.append(field.getAnnotation(DbFiled.class).value() + "  BLOB PRIMARY KEY,");
                    }
                } else {
                      /*
                    不支持的類型
                     */
                    continue;
                }
            }
            //循環完成后,最后一項會有 逗號 ,如果最后一個是逗號,則刪除最后一個字符
            if (stringBuffer.charAt(stringBuffer.length() - 1) == ',') {
                stringBuffer.deleteCharAt(stringBuffer.length() - 1);
            }
            //SQL 語句 收尾
            stringBuffer.append(")");
            Log.i(TAG, "createTable: " + stringBuffer.toString());
            return stringBuffer.toString();
        }
    
        @Override
        public Long insert(T entity) {
            Map<String, String> map = getValues(entity);
            ContentValues contentValues = getContentValues(map);
            return database.insert(tableName, null, contentValues);
        }
    
        /**
         * 獲取對應 model 屬性以及對應的注解值(表列名值)
         *
         * @param entity 對應 表結構的model
         * @return 返回 key= 列名,value=屬性的值          map集合
         */
        private Map<String, String> getValues(T entity) {
            HashMap<String, String> map = new HashMap<>();
            //獲取對應緩存 model 里面的屬性鍵
            Iterator<Field> fieldIterator = cacheMap.values().iterator();
            while (fieldIterator.hasNext()) {
                Field field = fieldIterator.next();
                field.setAccessible(true);
                try {
                    Object object = field.get(entity);
                    if (object == null) {
                        continue;
                    }
                    String value = object.toString();
                    String key = field.getAnnotation(DbFiled.class).value();
                    //遍歷 取出對應 屬性的值 以及對應的 注解值,并添加至Map里
                    if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
                        map.put(key, value);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            return map;
        }
    
        /**
         * 數據庫數據結構的封裝
         *
         * @param map 帶有 以表列名為鍵,的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 key = iterator.next();
                String value = map.get(key);
                if (value != null) {
                    contentValues.put(key, value);
                }
            }
            return contentValues;
        }
    
        @Override
        public int update(T entity, T where) {
            Map values = getValues(entity);
            ContentValues contentValues = getContentValues(values);
            //條件
            Map whereMap = getValues(where);
            Condition condition = new Condition(whereMap);
            return database.update(tableName, contentValues, condition.whereClause, condition.whereArgs);
        }
    
        class Condition {
            String whereClause;
            String[] whereArgs;
    
            public Condition(Map<String, String> whereClause) {
                boolean flag = false;
                if (true && flag) {
    
                }
                ArrayList list = new ArrayList();
                StringBuilder stringBuilder = new StringBuilder();
                // 這里之所以先添加 1=1 這個條件 是因為
                // SQL  where  后面需要給條件判斷,而下面 while 循環 直接添加了 and
                // SQL 語句就變成了 where and  這顯然不符合SQL語句
                // 因此 加上 1=1 就變成了  where 1=1 and xx。起了一個呈上去下的作用
    
                stringBuilder.append("1=1");
                Set keys = whereClause.keySet();
                Iterator iterator = keys.iterator();
                while (iterator.hasNext()) {
                    String key = (String) iterator.next();
                    String value = whereClause.get(key);
                    if (value != null) {
                        stringBuilder.append(" and " + key + " =?");
                        list.add(value);
                    }
                }
                this.whereClause = stringBuilder.toString();
                this.whereArgs = (String[]) list.toArray(new String[list.size()]);
            }
        }
    
        @Override
        public int delete(T where) {
            Map map = getValues(where);
            Condition condition = new Condition(map);
            return database.delete(tableName, condition.whereClause, condition.whereArgs);
        }
    
        @Override
        public List<T> query(T where) {
            return query(where, null, null, null, null, null
            );
        }
        //所有  條件
        @Override
        public List<T> query(T where, String groupBy, String orderBy, String having,Integer startIndex,
                             Integer limit) {
            String limitString=null;
            if(startIndex!=null&&limit!=null)
            {
                limitString=startIndex+" , "+limit;
            }
    
            Map map=getValues(where);
            Condition condition=new Condition(map);
            Cursor cursor=  database.query(tableName, null, condition.whereClause,
                    condition.whereArgs,
                    groupBy, having,
                    orderBy, limitString
            );
    //        封裝   --返回
            List<T> result = getResult(cursor, where);
            cursor.close();
            return result;
        }
    
    
    
    
    
        private List<T> getResult(Cursor cursor, T where) {
            ArrayList  list=new ArrayList();
            Object item;
            while (cursor.moveToNext()) {
                try {
    //                cachmap        ---對象中的成員變量    Filed    annotion-- tb_name
    //cacheMap    name  ---Filed       1
    //            tb_name       ---Filed  2
                    item=where.getClass().newInstance();
                    Iterator iterator=cacheMap.entrySet().iterator();
                    while (iterator.hasNext())
                    {
                        Map.Entry entry= (Map.Entry) iterator.next();
                        //tb_name
                        /**
                         * 得到列名
                         */
                        String colomunName= (String) entry.getKey();
    //                    通過列名查找到游標的索性
                        Integer colmunIndex= cursor.getColumnIndex(colomunName);
    //                    Filed
    //反射的成員 cursor
                        Field field= (Field) entry.getValue();
                        Class type=field.getType();
                        if(colmunIndex!=-1)
                        {
    //
                            if (type == String.class) {
                                field.set(item, cursor.getString(colmunIndex));
                            }else if(type==Double.class)
                            {
                                field.set(item,cursor.getDouble(colmunIndex));
                            }else  if(type==Integer.class)
                            {
                                field.set(item,cursor.getInt(colmunIndex));
                            }else if(type==Long.class)
                            {
                                field.set(item,cursor.getLong(colmunIndex));
                            }else  if(type==byte[].class)
                            {
                                field.set(item,cursor.getBlob(colmunIndex));
                                /*
                                不支持的類型
                                 */
                            }else {
                                continue;
                            }
    
                        }
    
                    }
                    list.add(item);
                } catch ( Exception e) {
                    e.printStackTrace();
                }
    
    
            }
    
            return list;
        }
    }

    代碼分析:

    在這個BaseDao 里面,幾乎分擔了數據表大部分的臟活累活,根據model結構自動生成對應SQL并創建對應表,以及基礎的增刪改查操作。

    2.3 建對應model 的Dao層

    1.UserDao

    public class UserDao<User> extends BaseDao<User> {
    
        @Override
        public Long insert(User entity) {
            return super.insert(entity);
        }
    
        @Override
        public List<User> query(User where) {
            return super.query(where);
        }
    
        @Override
        public int delete(User where) {
            return super.delete(where);
        }
    
        @Override
        public int update(User entity, User where) {
            return super.update(entity, where);
        }
    
        @Override
        public List<User> query(User where, String groupBy, String orderBy, String having, Integer startIndex, Integer limit) {
            return super.query(where, groupBy, orderBy, having, startIndex, limit);
        }
    }

    2.PhotoDao

    public class PhotoDao<Photo> extends BaseDao<Photo> {
    
        @Override
        public Long insert(Photo entity) {
            return super.insert(entity);
        }
    
        @Override
        public int update(Photo entity, Photo where) {
            return super.update(entity, where);
        }
    
        @Override
        public List<Photo> query(Photo where) {
            return super.query(where);
        }
    
        @Override
        public int delete(Photo where) {
            return super.delete(where);
        }
    }

    代碼分析:

    雖然 BaseDao 已經完成了幾乎所有的操作,但是一旦遇到多表查詢的時候,光是一個BaseDao遠遠不夠。所以這里還是選擇創建不同modelDao層,并繼承與BaseDao。也就是說,有多少表,最好就創建對應多少個Dao層。

    3、創建數據庫工廠

    public class BaseDaoFactory {
    
        private final String TAG = "hqk";
        private SQLiteDatabase sqLiteDatabase;
    
        private String sqliteDatabasePath;
    
        private static BaseDaoFactory instance = new BaseDaoFactory();
    
        //餓漢單例模式
        public static BaseDaoFactory getInstance() {
            return instance;
        }
    
        public BaseDaoFactory() {
            //讀者可隨意更改路徑以及對應數據庫名,這里演示暫時放在根目錄
            sqliteDatabasePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hqk.db";
            sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqliteDatabasePath, null);
            Log.i(TAG, "sqliteDatabasePath : " + sqliteDatabasePath);
            Log.i(TAG, "sqLiteDatabase : " + sqLiteDatabase.getPath());
        }
    
    
        /**
         * @param clazz
         * @param entityClass
         * @param <R>         我們在這可以把它看成某一個對象,它繼承與 BaseDao<T> ,而里面的T 就是下面的那個空對象
         * @param <T>         我們在這可以吧它看成某一個空對象 T
         * @return
         */
        public synchronized <R extends BaseDao<T>, T> R createBaseDao(Class<R> clazz, Class<T> entityClass) {
            BaseDao baseDao = null;
            try {
                baseDao = clazz.newInstance();
                baseDao.init(entityClass, sqLiteDatabase);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
    
            return (R) baseDao;
        }
    }

    代碼分析:

    這里也沒啥好分析的,就一個數據庫創建,以及對應model的初始化。唯一值得注意的就是初始化的時候用了倆個泛型,具體什么意思,可按照代碼注釋理解。

    4、創建對應model

    1.User

    @DbTable("tb_user")
    public class User {
        
        @DbPrimaryKey(value = "tb_id", isAuto = true)
        @DbFiled("tb_id")
        public Integer id;
        @DbFiled("tb_name")
        public String name;//
        
        @DbFiled("tb_age")
        public Integer age;
    
        public User(String name, Integer age) {
    
            this.name = name;
            this.age = age;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public User() {
        }
    
    
    }

    2.Photo

    @DbTable("tb_photo")
    public class Photo {
        @DbFiled("time")
        private  String time;
        @DbFiled("id")
        private  Long id;
        @DbFiled("path")
        private  String path;
    
        public Photo( ) {
        }
    
        public Photo(String time, Long id, String path) {
            this.time = time;
            this.id = id;
            this.path = path;
        }
    
        public void setTime(String time) {
            this.time = time;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public void setPath(String path) {
            this.path = path;
        }
    }

    代碼分析:

    這倆類就是對應表結構model 類,用到了對應注解,相信通過注解能夠清楚知道對應表結構是怎樣的。

    5、最終使用

    ainActivity

    public class MainActivity extends AppCompatActivity {
    
        UserDao<User> userDao;
    
        PhotoDao<Photo> photoDao;
    
        private ArrayList<User> listUser = new ArrayList<>();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            requestPermission(this);
        }
    
    
        public void save(View view) {
            User user = new User("hqk", 18);
            long size = userDao.insert(user);
            Photo photo = new Photo("time", System.currentTimeMillis(), "path");
            long photoSize = photoDao.insert(photo);
            Toast.makeText(this, "save line :   " + size, Toast.LENGTH_LONG).show();
        }
    
    
        public void update(View view) {
            User where = new User();
            where.setAge(18);
            int size = userDao.update(new User("TOM", 99), where);
            Toast.makeText(this, "update Size :   " + size, Toast.LENGTH_LONG).show();
        }
    
        public void delete(View view) {
            User where = new User();
            where.setAge(18);
            int size = userDao.delete(where);
            Toast.makeText(this, "delete Size :   " + size, Toast.LENGTH_LONG).show();
        }
    
        public void queryList(View view) {
            listUser.clear();
            listUser.addAll(userDao.query(new User()));
            Toast.makeText(this, "查詢條數為:" + listUser.size(), Toast.LENGTH_LONG).show();
        }
    
    
        public void requestPermission(
                Activity activity) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ActivityCompat.checkSelfPermission(activity,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(activity, new String[]{
                        Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE
                }, 1);
                return;
            }
            createTable();
    
    
        }
    
        private void createTable() {
            userDao = BaseDaoFactory.getInstance().createBaseDao(UserDao.class, User.class);
            photoDao = BaseDaoFactory.getInstance().createBaseDao(PhotoDao.class, Photo.class);
        }
    
        @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            createTable();
        }
    }

    關于Android架構中的數據庫框架該如何搭建就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    黑河市| 碌曲县| 张掖市| 宁蒗| 石河子市| 青浦区| 探索| 勐海县| 枞阳县| 阿瓦提县| 若尔盖县| 镇宁| 桐梓县| 斗六市| 香河县| 江都市| 青铜峡市| 金华市| 治多县| 于田县| 灌南县| 明水县| 通辽市| 黔南| 仁化县| 邻水| 芜湖市| 司法| 中江县| 东源县| 顺昌县| 多伦县| 龙陵县| 七台河市| 永川市| 额济纳旗| 江华| 乌兰浩特市| 电白县| 西吉县| 扶余县|