GreenDao2.0使用詳解

介紹

GreenDAO是一個對象關系映射(ORM)的框架,能夠提供相關接口娘锁,通過操作對象的方式去操作關系型數(shù)據(jù)庫。GreenDao官網(wǎng)介紹: greenDAO is a light & fast ORM solution for Android that maps objects to SQLite databases.

greenDao作為java對象和SQLite數(shù)據(jù)庫之間的橋梁

GreenDao的優(yōu)勢
greenDao與OrmLite舆吮、ActiveAndroid對比
  1. 輕量級
  2. 增刪改查操作快速
  3. 內存開銷小外莲,性能好
  4. Api接口完善,方便初學者使用
GreenDao2.0配置

在gradle中引入:

compile 'de.greenrobot:greendao:2.0.0'

GreenDao2.0使用
  • 創(chuàng)建本地數(shù)據(jù)庫及表
    新建一java工程降铸,導入greendao-generator-1.3.1.jar到libs中在旱,main文件中寫:
    public class ExampleDaoGenerator {
    public static void main(String[] args) throws Exception {
    //第一個參數(shù)是數(shù)據(jù)庫版本號,第二個參數(shù)是包名
    Schema schema = new Schema(version, "你的包名路徑");
    //給數(shù)據(jù)庫新增一張表
    addMessage(schema);
    //第二個參數(shù)是文件生成路徑
    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");
    }
    }
    執(zhí)行Main()方法谅畅,數(shù)據(jù)庫映射文件將會在LocalConstants.CODE_PATH路徑下生成登渣。

  • 數(shù)據(jù)庫的使用(表的增刪改查)
    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;
    }
    //查詢未讀消息數(shù)
    public int getNoReadMsg() {
      try {
          return messageEntityDao.queryBuilder().where(MessageEntityDao.Properties.IsRead.eq(false)).build().list().size();
      } catch (Exception e) {
          e.printStackTrace();
          return 0;
      }
    }
    //查消息類型對應的未讀消息條數(shù)
    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打開數(shù)據(jù)庫
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);
  }
  }

可以發(fā)現(xiàn),當數(shù)據(jù)庫版本更新時毡泻,會執(zhí)行onUpgrade方法胜茧,先刪除原有的數(shù)據(jù)表,再新建表仇味。

數(shù)據(jù)庫升級

當我們的app版本升級時竹揍,當對本地數(shù)據(jù)庫表結構修改時,就有必要對本地數(shù)據(jù)庫升級邪铲。我們只需要修改下DaoMaster文件中的SCHEMA_VERSION常量(增1),它就會執(zhí)行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);
}
......
}
有時我們并不想把原有的表數(shù)據(jù)也刪除,那要怎么做呢英染?
其核心思路是

  1. 把舊表改為臨時表
  2. 建立新表
  3. 臨時表數(shù)據(jù)寫入新表揽惹,刪除臨時表

代碼實現(xiàn):
/**
*表字段有改變的時候需要用到合并數(shù)據(jù)
*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) {
      //操作數(shù)據(jù)庫的更新
      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<? extends AbstractDao<?, ?>>... daoClasses) {
          generateTempTables(db, daoClasses);
          DaoMaster.dropAllTables(db, true);
          DaoMaster.createAllTables(db, false);
          restoreData(db, daoClasses);
      }

      private void generateTempTables(SQLiteDatabase 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) {
                          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<? 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 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<String> getColumns(SQLiteDatabase 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;
      }
  }

所以,當需要數(shù)據(jù)庫升級時四康,我們使用
DbOpenHelper helper = new DbOpenHelper(context,"xxx.db",null);
來打開數(shù)據(jù)庫搪搏。
講到這里,GreenDao2.0的使用基本已經(jīng)完了闪金,下一篇疯溺,我將為大家講解GreenDao3.0的優(yōu)化及使用论颅。
喜歡就點個贊哦。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末囱嫩,一起剝皮案震驚了整個濱河市恃疯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌墨闲,老刑警劉巖今妄,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鸳碧,居然都是意外死亡盾鳞,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進店門瞻离,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腾仅,“玉大人,你說我怎么就攤上這事琐脏≡茏” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵日裙,是天一觀的道長吹艇。 經(jīng)常有香客問我,道長昂拂,這世上最難降的妖魔是什么受神? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮格侯,結果婚禮上鼻听,老公的妹妹穿的比我還像新娘。我一直安慰自己联四,他們只是感情好撑碴,可當我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著朝墩,像睡著了一般醉拓。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上收苏,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天亿卤,我揣著相機與錄音,去河邊找鬼鹿霸。 笑死排吴,一個胖子當著我的面吹牛,可吹牛的內容都是我干的懦鼠。 我是一名探鬼主播钻哩,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼屹堰,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了憋槐?” 一聲冷哼從身側響起双藕,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阳仔,沒想到半個月后忧陪,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡近范,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年醇坝,在試婚紗的時候發(fā)現(xiàn)自己被綠了署辉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片每辟。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡塔淤,死狀恐怖,靈堂內的尸體忽然破棺而出斥杜,到底是詐尸還是另有隱情虱颗,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布蔗喂,位于F島的核電站忘渔,受9級特大地震影響,放射性物質發(fā)生泄漏缰儿。R本人自食惡果不足惜畦粮,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乖阵。 院中可真熱鬧宣赔,春花似錦、人聲如沸瞪浸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽对蒲。三九已至钩蚊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間齐蔽,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工床估, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留含滴,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓丐巫,卻偏偏與公主長得像谈况,于是被迫代替她去往敵國和親勺美。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內容

  • http://jinnianshilongnian.iteye.com/blog/2022468 Realm數(shù)據(jù)...
    天之大任閱讀 273評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理碑韵,服務發(fā)現(xiàn)赡茸,斷路器,智...
    卡卡羅2017閱讀 134,601評論 18 139
  • 前言: 上一篇簡介了greendao的數(shù)據(jù)庫的接入以及簡單的操作祝闻,既然涉及到數(shù)據(jù)庫中的數(shù)據(jù)占卧,那就必須考慮到加密問題...
    Smile__EveryDay閱讀 2,217評論 0 8
  • 以前開發(fā)用到數(shù)據(jù)庫時,基本上都是用android原生的sql語句联喘,寫那些語句時稍有不慎华蜒,就給你拋出一個except...
    BlainPeng閱讀 7,664評論 2 12
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法豁遭,內部類的語法叭喜,繼承相關的語法,異常的語法蓖谢,線程的語...
    子非魚_t_閱讀 31,587評論 18 399