zoukankan      html  css  js  c++  java
  • Android GreenDao操作外部DB数据库文件

    1.背景

    所谓外部数据库文件此处指的就是一个在外部单独创建的db文件,假设有这么一个场景,我们项目中有一些本地数据,不需要接口去获取的(不需要进行网络操作),写死的数据,比如全国各个省各个市的一些基本信息,每个市的信息可以作为表里的一条记录存放,在项目中使用,此时如何我们已经有了包含这些信息的db文件,我们就可以通过greendao来操作这个db文件,更具方便进行开发工作,当然这只是个模拟情况,至于合不合理,有没有更好的方式,此处不过多讨论,重点讲这么一种方式,这种方式可以用于一些不经常变化的数据。

    2.项目配置

    • 首先看一下项目结构:

    这里写图片描述

    res/raw目录存放的就是外部的db文件的压缩文件,我们可以打开看一下数据库结构,db文件包含两张表,student和teacher里面简单的插入了几条测试数据:

    这里写图片描述 
    这里写图片描述

    • 引入greendao库文件或者引用库工程:

    这里写图片描述

    2.代码实现

    实现之前先说一下具体的思路,程序运行,首先把raw目录下的db文件拷贝到数据库存储的默认目录,然后通过greendao的api对这个文件进行操作即可;

      • 我们需要获取应用db存储的路径,通过如下方式:
    private void getAppInfo()
        {
            // 获取packageManager的实例
            PackageManager packageManager = getPackageManager();
            // getPackageName()是你当前类的包名,0代表是获取版本信息
            try
            {
                packInfo = packageManager.getPackageInfo(getPackageName(), 0);
            }
            catch (NameNotFoundException e)
            {
                e.printStackTrace();
            }
        }
      • 通过以上方式即可获取到数据库的路径: 
        这里写图片描述

      • 拷贝操作:

    public static boolean copyRawDBToApkDb(Context context, int copyRawDbResId, String apkDbPath, String dbName,boolean refresh)
            throws IOException
        {
            boolean b = false;
    
            File f = new File(apkDbPath);
            if (!f.exists())
            {
                f.mkdirs();
            }
    
            File dbFile = new File(apkDbPath + dbName);
            b = isDbFileExists(dbFile,refresh);
            if (!b)
            {
                InputStream is = context.getResources().openRawResource(copyRawDbResId);
    
                ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
                ZipEntry entry;
    
                while ((entry = zis.getNextEntry()) != null)
                {
                    int size;
                    byte[] buffer = new byte[1024 * 2];
    
                    OutputStream fos = new FileOutputStream(apkDbPath + entry.getName());
                    BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.length);
    
                    while ((size = zis.read(buffer, 0, buffer.length)) != -1)
                    {
                        bos.write(buffer, 0, size);
                    }
                    bos.flush();
                    bos.close();
                }
                zis.close();
                is.close();
            }
            return !b;
        }

    此处是拷贝操作的关键代码,需要我们传入raw资源ID,数据库的拷贝路径,数据库文件名,是否覆盖已经存在的db文件,@return 拷贝是否成功,关于refresh参数,我们一般希望只拷贝一次,当我们在某些情况下更新了这个db文件的话就可以设置为true进行覆盖操作;

    • 使用greenDao java工程,生成外部db文件所对应表的实体类Dao类等代码:

    这里写图片描述

    上图中的DBController类是我封装的数据库操作类,更方便我们去进行操作,DBController的关键代码如下:

    /**
     * 外部数据库控制类
     */
    public class DBController
    {
        private static DaoMaster daoMasterEcmc;
    
        private static DaoMaster daoMasterSchool;
    
        // 默认DB
        private static DaoSession daoSessionDefault;
    
        // 拷贝的db
        private static DaoSession daoSchoolSession;
    
        /**
         * 默认数据库名称:localdata
         */
        public static final String DATABASE_NAME = "localdata.db";
    
        /**
         * 拷贝数据库名称:school
         */
        public static final String DATABASE_SCHOOL_NAME = "school.db";
    
        private static DaoMaster obtainMaster(Context context, String dbName)
        {
            return new DaoMaster(new DaoMaster.DevOpenHelper(context, dbName, null).getWritableDatabase());
        }
    
        private static DaoMaster getDaoMaster(Context context, String dbName)
        {
            if (dbName == null)
                return null;
            if (daoMasterEcmc == null)
            {
                daoMasterEcmc = obtainMaster(context, dbName);
            }
            return daoMasterEcmc;
        }
    
        private static DaoMaster getSchoolDaoMaster(Context context, String dbName)
        {
            if (dbName == null)
                return null;
            if (daoMasterSchool == null)
            {
                daoMasterSchool = obtainMaster(context, dbName);
            }
            return daoMasterSchool;
        }
    
        /**
         * 取得DaoSession
         *
         * @return
         */
        public static DaoSession getDaoSession(String dbName)
        {
    
            if (daoSchoolSession == null)
            {
                daoSchoolSession = getSchoolDaoMaster(MainApplication.getIns(), dbName).newSession();
            }
            return daoSchoolSession;
        }
    
        /**
         * 默认操作localdata数据库
         */
        public static DaoSession getDaoSession()
        {
    
            if (daoSessionDefault == null)
            {
                daoSessionDefault = getDaoMaster(MainApplication.getIns(), DATABASE_NAME).newSession();
            }
            return daoSessionDefault;
        }
    }
    • 可能我们还需要默认的greendao数据库进行其他的操作,至于默认的操作此处不再详细介绍,不了解的可以看greendao基本使用,此处我们演示的外部DB文件命名为school.db,默认的greenDao数据库命名为history.db,下面我们在MainActivity进行测试操作:
    public class MainActivity extends Activity
    {
        private StringBuilder builder;
    
        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            //创建默认的数据,并插入一条数据
            HistoryDao historyDao = DBLocalController.getDaoSession().getHistoryDao();
            History entity = new History();
            entity.setName("科罗拉多");
            entity.setImageUrl("http://www.baidu.com");
            historyDao.insert(entity);
            //拷贝外部DB文件到指定目录
            copyRawDB();
            //通过greendao查询外部db文件数据
            selDBData();
        }
    
        private void selDBData()
        {
            StudentDao student = DBController.getDaoSession(DBController.DATABASE_SCHOOL_NAME).getStudentDao();
            List<Student> students = student.queryBuilder().list();
            builder = new StringBuilder();
            for (int i = 0; i < students.size(); i++)
            {
                builder.append(students.get(i).getName() + "---");
            }
            Toast.makeText(MainActivity.this, builder.toString(), Toast.LENGTH_SHORT).show();
        }
    
        private void copyRawDB()
        {
            try
            {
                // 拷贝res/raw/xxxxdb.zip 到
                // /data/data/com.xinhang.mobileclient/databases/ 目录下面
                boolean isSuccess = DBUtils.copyRawDBToApkDb(MainActivity.this, R.raw.schooldb, DBUtils.APK_DB_PATH, DBUtils.ECMC_DB_NAME, false);
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
    
    }

    运行结果:

    这里写图片描述

    可以看到我们的外部db文件已经拷贝到数据库默认路径下,还有我们的默认数据库也创建成功;区分两个数据库的方式是通过DBLocalController.getDaoSession(name)方法,想操作哪个数据库传入对应的数据库名称即可,gif操作图如下;

    这里写图片描述


    源码下载:源码下载,有问题欢迎交流讨论!

  • 相关阅读:
    【闲聊PHP】编程界的萝莉小美女--PHP
    【福利资料】程序员各种优秀资料、神器及框架
    【夯实shell基础】shell基础面面观
    【Java学习系列】第4课--Java Web相关
    【夯实PHP基础】微信小程序开发 2017.02.06
    【文学文娱】2017.01.17 周二--《谈谈日本妹子(多图预警)》
    【日常开发】使用多种工具实现 sql查询没有结果的name
    【夯实Mysql基础】MySQL在Linux系统下配置文件及日志详解
    【读书笔记】2017.01.06 星期五 《大型网站架构技术》
    【文学文娱】2016.12.23 周五--《我眼中的过年》
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/9104460.html
Copyright © 2011-2022 走看看