Android greenDao3.0的开发实战,包括版本升级(二)

上一篇文章简单记录了greenDao的导入和使用,这篇文章则主要是记录在开发中使用greenDao,一些管理类的封装,

主要类的结构如下

其中DaoMaster、DaoSession、TopicHistoryBeanDao(与上文中UserDao是类似的)是用Make project 自动生成的。

主要思路是,数据库和表分开管理,因为我们可能随着开发进行,添加很多表,

DaoManager(数据库管理类)

public class DaoManager {
    private static DaoManager mInstance;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    private static final String DBNAME = "look_history_db";
    private DaoManager() {
        //数据库初始化

        DBHelper devOpenHelper = new DBHelper(MyApplication.getContext(),DBNAME,null);
        mDaoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());//是使用的哪个devOpenHelper.getWritableDb()/getWritableDatebase
        mDaoSession = mDaoMaster.newSession();
    }
    public DaoMaster getDaoMaster() {
        return mDaoMaster;
    }

    public DaoSession getSession() {
        return mDaoSession;
    }

    public static DaoManager getInstance() {
        if (mInstance == null) {
            mInstance = new DaoManager();
        }
        return mInstance;
    }
}

EntityManager(数据库表的管理类)

表管理类

/*
* 数据库中表的管理
* TopicHistoryBeanDao  是数据库中的一个表,这里可以添加很多表的获取,便于管理
 */

public class EntityManager {
    private static EntityManager entityManager;
    private TopicHistoryBeanDao historyBeanDao;

    public EntityManager() {
        historyBeanDao = DaoManager.getInstance().getSession().getTopicHistoryBeanDao();
    }

    /**
     * 创建单例
     *
     * @return
     */
    public static EntityManager getInstance() {
        if (entityManager == null) {
            entityManager = new EntityManager();
        }
        return entityManager;
    }

    public TopicHistoryBeanDao getHistoryBeanDao() {
        return historyBeanDao;
    }
}

HistroyTableManager(表的数据操作管理类)

对应的表的增删改查管理类,这里可以按照你需要的功能进行编写。不是必须这样些,只做提示。
我觉得还是把HistoryTopicBean的字段贴一下,不然可能会看的难受

TopicHistoryBean

@Entity
public class TopicHistoryBean {
    @Id(autoincrement = true)
    private Long id;
    private String tid;
    private String fid;
    private String forumname;
    private String icon;
    private String author;
    private String authorid;
    private String subject;
    private String postdate;
    private String like_count;
    private String replies;
    private String hits;
    private String attach;
    private long savetime;//保存时间

HistroyTableManager


public class HistroyTableManager {
    private static  HistroyTableManager mInstance;
    public TopicHistoryBeanDao historyBeanDao;

    private HistroyTableManager(){
        historyBeanDao=EntityManager.getInstance().getHistoryBeanDao();
    }
    /**
     * @return
     */
    public static HistroyTableManager getInstance() {
        if (mInstance == null) {
            mInstance = new HistroyTableManager();
        }
        return mInstance;
    }

    /**
     * 插入数据不能插入相同的帖子数据
     *
     * @param bean
     */
    public void insert(TopicListBean bean) {
        //当数据库中有该数据的时候,

        TopicHistoryBean historyBean = TopicHistoryBean.toTopicHistoryBean(bean);

        LogUtils.e("要插入的数据为:historyBean==" + historyBean.toString());

        //查询指定的作者和主题的历史记录
        List<TopicHistoryBean> list = getTheTopics(bean.getAuthor(), bean.getSubject());
        boolean isHas = false;
        for (int i = 0; i < list.size(); i++) {
            if (list.get(i).equals(historyBean)) {
                isHas = true;
            }
        }
        //如果有的话,就进行修改数据
        if (isHas) {
            LogUtils.e("当前帖子已经存在,进行修改参数操作");
        } else {
            historyBeanDao.insert(historyBean);
            LogUtils.e("插入数据");
        }


    }

    public void insert(TopicHistoryBean bean) {


        historyBeanDao.insert(bean);
    }

    /**
     * 删除某一条数据
     *
     * @param bean
     */
    public void delete(TopicHistoryBean bean) {
        historyBeanDao.delete(bean);
    }

    /**
     * 删除全部数据
     */
    public void deleteAll() {
        historyBeanDao.deleteAll();
    }

    /**
     * 查询全部数据
     *
     * @return
     */
    public List<TopicHistoryBean> getAllHistory() {
        return historyBeanDao.queryBuilder().list();
    }


    /**
     * 查询指定的浏览历史是否已经在数据库中
     *
     * @return
     */
    public List<TopicHistoryBean> getTheTopics(String name, String subject) {
        return historyBeanDao.queryBuilder()
                .where(TopicHistoryBeanDao.Properties.Author.eq(name), TopicHistoryBeanDao.Properties.Subject.eq(subject))
                .build()
                .list();
    }

}

版本升级

  • greenDao3.0的版本升级,基本思路是:
创建临时表-->删除原表-->创建新表-->复制临时表数据到新表并删除临时表
并且我们新增加的和修改的字段做好为String类型,避免字段不能为null的情况发生

数据库到底该怎么升级

  • MigrationHelper(数据迁移类)

public class MigrationHelper {

    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION =
            "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";

    private static MigrationHelper instance;


    public  static  MigrationHelper getInstance(){
        if (instance==null){
            instance = new MigrationHelper();
        }
        return  instance;
    }

    /**
     * 数据迁移
     * @param db
     * @param daoClasses
     */
    public  void  migrate(Database db, Class<? extends AbstractDao<?,?>>... daoClasses ){
        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
        LogUtils.i("greenDAO", "MigrationHelper---migrate");
    }


    /**
     * 生成临时列表
     * @param db
     * @param daoClasses
     */
    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch (Exception exception) {
                    }

                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

                    if (daoConfig.properties[j].primaryKey) {
                        createTableStringBuilder.append(" PRIMARY KEY");
                    }

                    divider = ",";
                }
            }
            createTableStringBuilder.append(");");

            db.execSQL(createTableStringBuilder.toString());

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tableName).append(";");

            db.execSQL(insertTableStringBuilder.toString());
        }
    }

    private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList();

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;
                if (getColumns(db, tempTableName).contains(columnName)) {
                    properties.add(columnName);
                }
            }

            StringBuilder insertTableStringBuilder = new StringBuilder();
            insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();

            dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);

            db.execSQL(insertTableStringBuilder.toString());
            db.execSQL(dropTableStringBuilder.toString());
        }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)) {
            return "TEXT";
        }
        if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
            return "INTEGER";
        }
        if (type.equals(Boolean.class)) {
            return "BOOLEAN";
        }

        Exception exception =
                new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
        throw exception;
    }

    private static List<String> getColumns(Database db, String tableName) {
        List<String> columns = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
            if (cursor != null) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null) cursor.close();
        }
        return columns;
    }
}
  • DBHelper(自定义Helper类)

这里进行版本升级时的数据迁移,等操作

public class DBHelper extends DaoMaster.OpenHelper {





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

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {

        //需要对版本升级进行处理
        super.onUpgrade(db, oldVersion, newVersion);
        LogUtils.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
        if (oldVersion < newVersion) {
            LogUtils.e("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
            MigrationHelper.getInstance().migrate(db, TopicHistoryBeanDao.class);
            //更改过的实体类(新增的不用加)   更新UserDao文件 可以添加多个  XXDao.class 文件
//             MigrationHelper.getInstance().migrate(db, UserDao.class,XXDao.class);
        }

    }
}
  • 添加字段进行编译

    1.在TopicHistoryBean 中添加一个字段String newColum–>Build–>Make Project 编译后自动将该字段添加到构造函数中,并实现set,get方法。

@Entity
public class TopicHistoryBean {
    @Id(autoincrement = true)
    private Long id;
    private String tid;
    private String fid;
    private String forumname;
    private String icon;
    private String author;
    private String authorid;
    private String subject;
    private String postdate;
    private String like_count;
    private String replies;
    private String hits;
    private String attach;
    private long savetime;//保存时间
    private String newColum;//新增字段

    @Generated(hash = 461609634)
    public TopicHistoryBean(Long id, String tid, String fid, String forumname, String icon, String author, String authorid, String subject, String postdate,
            String like_count, String replies, String hits, String attach, long savetime, String newColum) {
        this.id = id;
        this.tid = tid;
        this.fid = fid;
        this.forumname = forumname;
        this.icon = icon;
        this.author = author;
        this.authorid = authorid;
        this.subject = subject;
        this.postdate = postdate;
        this.like_count = like_count;
        this.replies = replies;
        this.hits = hits;
        this.attach = attach;
        this.savetime = savetime;
        this.newColum = newColum;
    }
    ...

     public String getNewColum() {
        return this.newColum;
    }


    public void setNewColum(String newColum) {
        this.newColum = newColum;
    }
}

2.将module中build.gradle中的版本号修改为比当前大–>Sync Now–>as 中的绿箭头安装到模拟器或真机中。

 greendao {
        schemaVersion 2   //新版本
        daoPackage 'com.*****.db'//这个是生成代码保存的包名
        targetGenDir 'src/main/java'//保存到java代码路径
    }

3.查看日志

如果出现这条日志,说明你的数据表已经升级ok了

10-19 12:11:48.782 7925-7925/? E/version: [ className=com.alpha.alphaapp.db.DBHelper,methodName=onUpgrade,lineNumber=34 ] 1---先前和更新之后的版本---2

打印保存的HistoryTopicBean,很显然,我们新添的字段newColum,已经存在,但是因为前面的数据没有该字段,所以为null

TopicHistoryBean{id=1, tid='3468', fid='9', forumname='夺晶战神界', icon='http://cdn.gdalpha.com/icon/100/100.jpg', author='大表姐', authorid='26', subject='【官网嘉年华】爆裂王者大作战震撼上线,快来开启你的探索之旅!', postdate='1502251719', like_count='17', replies='27', hits='1419', attach='[]', savetime=1508384399, newColum='null'}

以上就是我的greenDao的使用过程,如果大家在使用过程中存在发现,欢迎及时反馈。共同进步。

Demo下载地址(非本文Demo)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值