GreenDao2.0使用详解

介绍

GreenDAO是一个对象关系映射(ORM)的框架,能够提供相关接口,通过操作对象的方式去操作关系型数据库。GreenDao官网介绍: greenDAO is a light & fast ORM solution for Android that maps objects to SQLite databases.

GreenDao2.0使用详解_第1张图片
greenDao作为java对象和SQLite数据库之间的桥梁

GreenDao的优势
GreenDao2.0使用详解_第2张图片
greenDao与OrmLite、ActiveAndroid对比
  1. 轻量级
  2. 增删改查操作快速
  3. 内存开销小,性能好
  4. Api接口完善,方便初学者使用
GreenDao2.0配置

在gradle中引入:

compile 'de.greenrobot:greendao:2.0.0'

GreenDao2.0使用
  • 创建本地数据库及表
    新建一java工程,导入greendao-generator-1.3.1.jar到libs中,main文件中写:
    public class ExampleDaoGenerator {
    public static void main(String[] args) throws Exception {
    //第一个参数是数据库版本号,第二个参数是包名
    Schema schema = new Schema(version, "你的包名路径");
    //给数据库新增一张表
    addMessage(schema);
    //第二个参数是文件生成路径
    new DaoGenerator().generateAll(schema, LocalConstants.CODE_PATH);
    }
    private static void addMessage(Schema schema) {
    //表实体,会对应生成一张表
    Entity note = schema.addEntity("MessageEntity");
    //给表添加一个主键
    note.addStringProperty("msgId").primaryKey().notNull();
    //boolean类型字段,对应列名
    note.addBooleanProperty("isRead");
    //字符类型字段,对应列名
    note.addStringProperty("createTime");
    }
    }
    执行Main()方法,数据库映射文件将会在LocalConstants.CODE_PATH路径下生成。

  • 数据库的使用(表的增删改查)
    public class DbHelper {
    private final static String DB_NAME = "xxx.db";
    private static volatile DbHelper dbHelper;
    private DaoSession daoSession;
    private DaoMaster daoMaster;
    private MessageEntityDao messageEntityDao;
    public static DbHelper getInstance() {
    if (null == dbHelper) {
    synchronized (DbHelper.class) {
    if (null == dbHelper) {
    dbHelper = new DbHelper();
    dbHelper.daoSession = dbHelper.getDaoSession(XxxApplication.getInstance());
    dbHelper.messageEntityDao = dbHelper.daoSession.getMessageEntityDao();
    }
    }
    }
    return dbHelper;
    }
    private DbHelper() {

        }
    
      private DaoSession getDaoSession(Context context) {
        if (daoSession == null) {
          if (daoMaster == null) {
              daoMaster = getDaoMaster(context);
          }
          daoSession = daoMaster.newSession();
        }
        return daoSession;
      }
      private DaoMaster getDaoMaster(Context context) {
      if (daoMaster == null) {
          DaoMaster.OpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
          daoMaster = new DaoMaster(helper.getWritableDatabase());
      }
      return daoMaster;
    }
    //保存一条消息
    public long saveMessageEntity(MessageEntity messageEntity) {
      if (null == messageEntity) {
          return -1;
      }
      long result = -1;
      try {
          result = messageEntityDao.insertOrReplace(messageEntity);
      } catch (ClassCastException ex) {
          MLog.e("ClassCastException", "ClassCastException");
      } catch (Exception ex) {
          ex.printStackTrace();
      }
      return result;
    }
    //查询未读消息数
    public int getNoReadMsg() {
      try {
          return messageEntityDao.queryBuilder().where(MessageEntityDao.Properties.IsRead.eq(false)).build().list().size();
      } catch (Exception e) {
          e.printStackTrace();
          return 0;
      }
    }
    //查消息类型对应的未读消息条数
    public int getNoReadMsgCountByMsgType(String msgType) {
      try {
          return messageEntityDao.queryBuilder().where( MessageEntityDao.Properties.MsgType.eq(msgType), MessageEntityDao.Properties.IsRead.eq(false)).build().list().size();
      } catch (Exception e) {
          e.printStackTrace();
          return 0;
      }
    }
    //查询消息
    public MessageEntity getMsgByMsgId(String msgId) {
        try {
          return messageEntityDao.queryBuilder().where(MessageEntityDao.Properties.MsgId.eq(msgId)).build().unique();
          } catch (Exception e) {
          e.printStackTrace();
          return null;
          }
      }
    }
    

说明:
使用DevOpenHelper打开数据库
DaoMaster.DevOpenHelper helper = new DevOpenHelper(context,"xxx.db",null);
我们查看下DevOpenHelper内容
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}

  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
      Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
      dropAllTables(db, true);
      onCreate(db);
  }
  }

可以发现,当数据库版本更新时,会执行onUpgrade方法,先删除原有的数据表,再新建表。

数据库升级

当我们的app版本升级时,当对本地数据库表结构修改时,就有必要对本地数据库升级。我们只需要修改下DaoMaster文件中的SCHEMA_VERSION常量(增1),它就会执行onUpgrade()。
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 128;
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
MessageEntityDao.createTable(db, ifNotExists);
}
......
}
有时我们并不想把原有的表数据也删除,那要怎么做呢?
其核心思路是

  1. 把旧表改为临时表
  2. 建立新表
  3. 临时表数据写入新表,删除临时表

代码实现:
/**
*表字段有改变的时候需要用到合并数据
*Created by wangfengkai on 17/3/11.
*Github:https://github.com/github/jxwangfengkai
*/
public class DbOpenHelper extends DaoMaster.OpenHelper {
public DbOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
      //操作数据库的更新
      MigrationHelper.getInstance().migrate(sqLiteDatabase, MessageEntityDao.class);
    }
  }

  /**
   * 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 final String TAG = "MigrationHelper";
      private static volatile MigrationHelper instance;

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

      public void migrate(SQLiteDatabase db, Class>... daoClasses) {
          generateTempTables(db, daoClasses);
          DaoMaster.dropAllTables(db, true);
          DaoMaster.createAllTables(db, false);
          restoreData(db, daoClasses);
      }

      private void generateTempTables(SQLiteDatabase db, Class>... 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 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) {
                          Log.e(TAG, "CrashType:" + daoConfig.properties[j].type);
                          exception.printStackTrace();
                      }
                      createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

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

                      divider = ",";
                  }
              }
              createTableStringBuilder.append(");");
              String createSql = createTableStringBuilder.toString();
              if (!createSql.contains("();")) {
                  //说明没有表
                  db.execSQL(createSql);
                  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(";");

                  String insertTableSql = insertTableStringBuilder.toString();
                  Log.e(TAG, daoConfig.tablename + "__insertTableSql:" + insertTableSql);
                  db.execSQL(insertTableSql);
              }
          }
      }

      private void restoreData(SQLiteDatabase db, Class>... 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 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 IF EXISTS ").append(tempTableName);

              String insertSQL = insertTableStringBuilder.toString();
              if (properties.size() > 0) {
                  Log.e(TAG, daoConfig.tablename + "__restoreData__insertSQL:" + insertSQL);
                  db.execSQL(insertSQL);
              }
              String dropTableSql = dropTableStringBuilder.toString();
              Log.e(TAG, daoConfig.tablename + "__restoreData__dropTableSql:" + dropTableSql);
              db.execSQL(dropTableSql);
          }
      }

      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) || type.equals(int.class) || type.equals(Boolean.class) || type.equals(boolean.class)) {
              return "INTEGER";
          }

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

      private static List getColumns(SQLiteDatabase db, String tableName) {
          List 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;
      }
  }

所以,当需要数据库升级时,我们使用
DbOpenHelper helper = new DbOpenHelper(context,"xxx.db",null);
来打开数据库。
讲到这里,GreenDao2.0的使用基本已经完了,下一篇,我将为大家讲解GreenDao3.0的优化及使用。
喜欢就点个赞哦。

你可能感兴趣的:(GreenDao2.0使用详解)