栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > .Net

GreenDao

.Net 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

GreenDao

一、数据库升级(如增加字段)

1、增加phone

@Entity
public class UserModel {
    @Id(autoincrement = true)
    private Long id; //主键
    private String name; //姓名
    private String phone;//电话
}

2、修改版本号1->2

greendao {
    //数据库的版本
    schemaVersion 2
    //设置DaoMaster、DaoSession、Dao包名,即这些类存放的路径。
    daoPackage 'cn.lpf.demo.database'
    //设置DaoMaster、DaoSession、Dao目录
    targetGenDir 'src/main/java'
}

3、Build->Make Project->会自动更新DaoMaster、UserModel、UserModelDao文件,至此已完成升级,下面是数据库工具类,方便使用。

public class GreenDaoUtil {
    private static final String DB_NAME = "user.db";
    private static final GreenDaoUtil INSTANCE = new GreenDaoUtil();
    private DaoSession daoSession;
    private SQLiteDatabase database;

    private GreenDaoUtil() {}

    public static GreenDaoUtil getInstance() {
        return INSTANCE;
    }

    
    public void initDataBase(Context context) {
        
        //通过DaoMaster的内部类DevOpenHelper,可得到一个SQLiteOpenHelper对象。
        DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper
                (context, DB_NAME, null); 
        database = devOpenHelper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(database);
        daoSession = daoMaster.newSession();
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }

    public UserModelDao getUserModelDao() {
        return daoSession.getUserModelDao();
    }
}
UserModel userModel = new UserModel();
userModel.setName("xiao");
userModel.setPhnoe("1821456123");
GreenDaoUtil.getInstance().getMediaRecordDao().insert(userModel);

4、默认升级后原有数据将会被清除,以下是默认生成的升级代码DaoMaster内部类

   public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            //清除所有表然后重新创建
            dropAllTables(db, true);
            onCreate(db);
        }
    }

5、往往我们升级仍需要原有数据,则需要我们进行自定义,具体方案如下

(1)将所有表生成相应的临时表,将数据保存至临时表中

(2)删除全部原有的正式表

(3)生成全部新的正式表

(4)将临时表的数据恢复到新的正式表中(其中如果新增字段是数字类型如int,而临时表中没有该字段则值为空,而空赋值给新表的int型会发生异常,因此需要先将临时表中添加没有的列并赋上默认值)

以下是具体实现代码,只需修改GreenDaoUtil即可实现,升级流程还是以上步骤即可

public class GreenDaoUtil {
    private static final String DB_NAME = "dinduoduo_greendaoutil.db";

    private static class SingleHolder {
        private static final GreenDaoUtil INSTANCE = new GreenDaoUtil();
    }

    public static GreenDaoUtil getInstance() {
        return GreenDaoUtil.SingleHolder.INSTANCE;
    }

    private GreenDaoUtil() { }

    private DaoSession daoSession;
    private SQLiteDatabase database;

    
    public void initDataBase(Context context) {
        //通过继承DaoMaster的内部类DevOpenHelper自定义升级
        MyDevOpenHelper devOpenHelper = new MyDevOpenHelper(context, DB_NAME, null); //数据库名称
        database = devOpenHelper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(database);
        daoSession = daoMaster.newSession();
        //校验是否所有表都已记录
        if (daoSession.getAllDaos().size() != getAllDaoClass().size()){
            throw new RuntimeException("检查所有表是否都已知GreenDaoUtil.getAllDaoClass()中");
        }
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }

    public MediaRecordModelDao getMediaRecordDao() {
        return daoSession.getMediaRecordModelDao();
    }

    
    public List>> getAllDaoClass(){
        List>> list = new ArrayList();
        list.add(UserModelDao.class);
        return list;
    }

    
    private static class MyDevOpenHelper extends DaoMaster.DevOpenHelper {

        public MyDevOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            //将所有表备份至临时表
            for (Class daoClass: GreenDaoUtil.getInstance().getAllDaoClass()) {
                GreenDaoUtil.getInstance().creatTempTable(db, daoClass);
            }
            //清除所有存在的表(除临时表)
            DaoMaster.dropAllTables(db, true);
            //重新创建所有表
            DaoMaster.createAllTables(db, false);
            //从临时表恢复数据
            for (Class daoClass: GreenDaoUtil.getInstance().getAllDaoClass()) {
                GreenDaoUtil.getInstance().restoreData(db, daoClass);
            }
        }
    }

    
    private void creatTempTable(Database db, Class> daoClass){
        DaoConfig daoConfig = new DaoConfig(db, daoClass);
        String tableName = daoConfig.tablename;
        String tempTableName = daoConfig.tablename.concat("_TEMP");

        StringBuilder dropTableStringBuilder = new StringBuilder();
        dropTableStringBuilder.append("DROP TABLE IF EXISTS ").append(tempTableName).append(";");
        db.execSQL(dropTableStringBuilder.toString());
        StringBuilder createTableStringBuilder = new StringBuilder();
        createTableStringBuilder.append("CREATE TEMPORARY TABLE ").append(tempTableName);
        createTableStringBuilder.append(" AS SELECT * FROM ").append(tableName).append(";");
        db.execSQL(createTableStringBuilder.toString());
    }

    
    private void restoreData(Database db, Class> daoClass){
        DaoConfig daoConfig = new DaoConfig(db, daoClass);
        String tempTableName = daoConfig.tablename.concat("_TEMP");
        //获取临时表所有列名
        List tempTableColumnNameList = getColumnNames(db, tempTableName);
        //正式表所有列名集合
        List columnNameList = new ArrayList<>();
        for (Property property : daoConfig.properties){
            //如果临时表中无正式表的列则添加该列,用于解决数字类型如int赋值为null导致异常
            if (!tempTableColumnNameList.contains(property.columnName)){
                StringBuilder alterTableStringBuilder = new StringBuilder();
                alterTableStringBuilder.append("ALTER TABLE ").append(tempTableName);
                alterTableStringBuilder.append(" ADD COLUMN ").append(property.columnName);
                if (property.type == byte.class || property.type == Byte.class){
                    alterTableStringBuilder.append(" INTEGER DEFAULT 0");
                } else if (property.type == short.class || property.type == Short.class){
                    alterTableStringBuilder.append(" INTEGER DEFAULT 0");
                }else if (property.type == int.class || property.type == Integer.class){
                    alterTableStringBuilder.append(" INTEGER DEFAULT 0");
                }else if (property.type == long.class || property.type == Long.class){
                    alterTableStringBuilder.append(" Long DEFAULT 0");
                }else if (property.type == float.class || property.type == Float.class){
                    alterTableStringBuilder.append(" REAL DEFAULT 0");
                }else if (property.type == double.class || property.type == Double.class){
                    alterTableStringBuilder.append(" REAL DEFAULT 0");
                }else if (property.type == boolean.class || property.type == Boolean.class){
                    alterTableStringBuilder.append(" INTEGER DEFAULT 0");
                }else if (property.type == byte[].class || property.type == Byte[].class){
                    alterTableStringBuilder.append(" BLOB");
                }else if (property.type == java.util.Date.class){
                    alterTableStringBuilder.append(" INTEGER");
                }else {
                    alterTableStringBuilder.append(" TEXT");
                }
                db.execSQL(alterTableStringBuilder.toString());
            }
            columnNameList.add(property.columnName);
        }
        if (columnNameList.size() > 0) {
            final String columnSQL = TextUtils.join(",", columnNameList);
            StringBuilder insertTableStringBuilder = new StringBuilder();
            insertTableStringBuilder.append("INSERT INTO ").append(daoConfig.tablename).append(" (");
            insertTableStringBuilder.append(columnSQL);
            insertTableStringBuilder.append(") SELECt ");
            insertTableStringBuilder.append(columnSQL);
            insertTableStringBuilder.append(" FROM ").append(tempTableName);
            insertTableStringBuilder.append(";");
            db.execSQL(insertTableStringBuilder.toString());
        }
        StringBuilder dropTableStringBuilder = new StringBuilder();
        dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
        db.execSQL(dropTableStringBuilder.toString());
    }
    
    private List getColumnNames(Database db, String tableName) {
        List columns = null;
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 0", null);
            if (null != cursor && cursor.getColumnCount() > 0) {
                columns = Arrays.asList(cursor.getColumnNames());
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null){
                cursor.close();
            }
            if (null == columns){
                columns = new ArrayList<>();
            }
        }
        return columns;
    }
}

二、多渠道打包输出多个APP的场景

首先需要明白以上步骤2中daoPackage、targetGenDir用来配置生成代码的位置,只是在Make Project进行执行,不参与编译及打包,而参与编辑的是生成后的代码类

1、如果应用A和应用B使用的表结构没有差异,则以上步骤2生成代码位置无需改动即可,编译不同渠道都会使用该目录下的代码

2、应用A使用数据表UserModel,应用B使用的数据表DogModel
两个表字段存在差异,需要根据不同的渠道生成不同的代码,在以上步骤2中,分别定义和Make Project,最终在项目目录下即生成应用A所需的代码又生成应用B所需的代码,然后根据渠道使用相应的数据库代码即可

greendao {
    //A应用数据库的版本
    schemaVersion 2
    //A应用设置DaoMaster、DaoSession、Dao包名,即这些类存放的路径。
    daoPackage 'cn.lpf.demo.database.a'
    //A应用设置DaoMaster、DaoSession、Dao目录
    targetGenDir 'src/main/java'

 
    //B应用数据库的版本
    schemaVersion 4
    //B应用设置DaoMaster、DaoSession、Dao包名,即这些类存放的路径。
    daoPackage 'cn.lpf.demo.database.b'
    //B应用设置DaoMaster、DaoSession、Dao目录
    targetGenDir 'src/main/java'
}

生成代码目录

根据不同的渠道生成相应的数据库

public class GreenDaoUtil {
    private static final String A_DB_NAME = "user.db";
    private static final String B_DB_NAME = "dog.db";
    private static final GreenDaoUtil INSTANCE = new GreenDaoUtil();
    private com.lpf.demo.database.a.DaoSession daoSessionA;
    private com.lpf.demo.database.b.DaoSession daoSessionB;
    private SQLiteDatabase databaseA;
    private SQLiteDatabase databaseB;

    private GreenDaoUtil() {}

    public static GreenDaoUtil getInstance() {
        return INSTANCE;
    }

    
    public void initDataBase(Context context) {
        //通过DaoMaster的内部类DevOpenHelper,可得到一个SQLiteOpenHelper对象。
        if("A".equals(BuildConfig.PRODUCT)){
            com.lpf.demo.database.a.DaoMaster.DevOpenHelper devOpenHelper = new com.lpf.demo.database.a.DaoMaster.DevOpenHelper
                (context, A_DB_NAME, null); 
            databaseA = devOpenHelper.getWritableDatabase();
            com.lpf.demo.database.a.DaoMaster daoMasterA = new com.lpf.demo.database.a.DaoMaster(databaseA);
            daoSessionA = daoMasterA.newSession();
        }else if("B".equals(BuildConfig.PRODUCT)){
            com.lpf.demo.database.b.DaoMaster.DevOpenHelper devOpenHelper = new 
            com.lpf.demo.database.b.DaoMaster.DevOpenHelper
                (context, B_DB_NAME, null); 
            databaseB = devOpenHelper.getWritableDatabase();
            com.lpf.demo.database.b.DaoMaster daoMasterB = new com.lpf.demo.database.b.DaoMaster(databaseB);
            daoSessionB = daoMasterB.newSession();
        }       
    }

    public com.lpf.demo.database.a.DaoSession getDaoSessionA() {
        return daoSessionA;
    }

    public UserModelDao getUserModelDao() {
        return daoSessionA.getUserModelDao();
    }

    public com.lpf.demo.database.b.DaoSession getDaoSessionB() {
        return daoSessionB;
    }

    public DogModelDao getDogModelDao() {
        return daoSessionB.getDogModelDao();
    }
}

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/983556.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号