GreenDao3 使用說明

izdv7003 8年前發布 | 34K 次閱讀 數據庫

GreenDao 3

一個將對象映射到 SQLite 數據庫中的輕量且快速的ORM解決方案

導入

  • 在項目的 build.gradle 添加:
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'
    }
}

// 使用數據庫升級輔助GreenDaoUpgradeHelper時添加 allprojects { repositories { ... maven { url "

  • 在模組的 build.gradle 中添加:
  • apply plugin: 'org.greenrobot.greendao'

    dependencies { compile 'org.greenrobot:greendao:3.2.0'

        // 數據庫加密時添加
        compile 'net.zetetic:android-database-sqlcipher:3.5.1'
    
        // 使用數據庫升級輔助GreenDaoUpgradeHelper時添加
        compile 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v1.2.0'
    

    }</code></pre>

    • 設置 Schema,在模組的 build.gradle 中添加:
      • schemaVersion:數據庫schema版本號,通過 *OpenHelpers 遷移數據,schema改變值增加。默認為1
      • daoPackage:生成DAOs、DaoMaster、DaoSession的包名。默認為entities所在包名。
      • targetGenDir:生成DAOs、DaoMaster、DaoSession的目錄。默認為 build/generated/source/greendao
      • generateTests: 設置 true 自動生成單元測試。
      • targetGenDirTests: 設置生成單元測試目錄。默認為 src/androidTest/java
      </li> </ul>
      greendao {
          schemaVersion 1
          daoPackage 'com.example.greendaodemo.dao'
          targetGenDir 'src/main/java'
      }
      • 混淆
      ### greenDAO 3
      -keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
      public static java.lang.String TABLENAME;
      }
      -keep class **$Properties

      If you do not use SQLCipher:

      -dontwarn org.greenrobot.greendao.database.**

      If you do not use RxJava:

      -dontwarn rx.**</code></pre>

      基本用法

      實體

      @Entity(
              // schema 名,多個 schema 時設置關聯實體。插件產生不支持,需使用產生器
              // schema = "myschema",

          // 標記一個實體是否處于活動狀態,活動實體有 update、delete、refresh 方法。默認為 false
          active = false,
      
          // 表名,默認為類名
          nameInDb = "AWESOME_USERS",
      
          // 定義多列索引
          indexes = {
                  @Index(value = "name DESC", unique = true)
          },
      
          // 標記是否創建表,默認 true。多實體對應一個表或者表已創建,不需要 greenDAO 創建時設置 false
          createInDb = true,
      
          // 是否產生所有參數構造器。默認為 true。無參構造器必定產生
          generateConstructors = true,
      
          // 如果沒有 get/set 方法,是否生成。默認為 true
          generateGettersSetters = true
      

      ) public class User { // 主鍵,autoincrement設置自增 @Id(autoincrement = true) private Long id;

       // 唯一,默認索引
       @Unique
       private Long userId;
      
       // 列名,默認使用變量名。變化:customName --> CUSTOM_NAME
       @Property(nameInDb = "USERNAME")
       private String name;
      
       // 索引,unique設置唯一,name設置索引別名
       @Index(unique = true)
       private long fk_dogId;
      
       // 非空
       @NotNull
       private String horseName;
      
       // 忽略,不持久化,可用關鍵字transient替代
       @Transient
       private int tempUsageCount;
      
       // 對一,實體屬性與外聯實體中的ID相對應。默認自動自動生成。fk和對象聯動,同時改變。對象懶加載
       @ToOne(joinProperty = "fk_dogId")
       private Dog dog;
      
       // 對多,referencedJoinProperty 指定實體中與外聯實體屬性相對應的外鍵
       @ToMany(referencedJoinProperty = "fk_userId")
       private List<Cat> cats;
      
       // 對多,@JoinProperty注解:name 實體中的屬性;referencedName 外聯實體中的屬性。
       @ToMany(joinProperties = {
                       @JoinProperty(name = "horseName", referencedName = "name")
       })
       private List<Horse> horses;
      
       // 對多,@JoinEntity注解:entity 中間表;sourceProperty 實體屬性;targetProperty 外鏈實體屬性
       @ToMany
       @JoinEntity(
                       entity = JoinSheepToUser.class,
                       sourceProperty = "uId",
                       targetProperty = "sId"
       )
       private List<Sheep> sheep;
      
      

      }

      @Entity public class JoinSheepToUser {

      @Id
      private Long id;
      
      private Long uId;
      
      private Long sId;
      

      }

      @Entity public class Sheep {

      @Id
      private Long id;
      
      private String name;
      

      }</code></pre>

      • @Generated :greenDao生產代碼注解,手動修改報錯
      • @Keep :替換@Generated,greenDao不再生成,也不報錯。@Generated(無hash)也有相同的效果
      • @ToOne :fk 和對象聯動,同時改變。對象懶加載,第一次請求后立即獲取對象
      • @ToMany :集合懶加載并緩存,之后獲取集合不查找數據庫,即集合數據不變。須手動修改集合,或調用reset方法清理集合

      初始化

      // Application 中執行
      // DevOpenHelper 每次數據庫升級會清空數據,一般用于開發
      DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
      Database db = helper.getWritableDb();
      DaoSession daoSession = new DaoMaster(db).newSession();

      // 在使用的地方獲取 DAO NoteDao noteDao = daoSession.getNoteDao();</code></pre>

      Dao 增加

      long     insert(T entity)  // 插入指定實體
      void     insertInTx(T... entities)
      void     insertInTx(java.lang.Iterable<T> entities)
      void     insertInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey)
      long     insertWithoutSettingPk(T entity)  // 插入指定實體,無主鍵
      long     insertOrReplace(T entity)  // 插入或替換指定實體
      void     insertOrReplaceInTx(T... entities)
      void     insertOrReplaceInTx(java.lang.Iterable<T> entities)
      void     insertOrReplaceInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey)
      void     save(T entity)  // 依賴指定的主鍵插入或修改實體
      void     saveInTx(T... entities)
      void     saveInTx(java.lang.Iterable<T> entities)

      Dao 刪除

      void     deleteAll()  // 刪除所有
      void     delete(T entity)  // 刪除指定的實體
      void     deleteInTx(T... entities)
      void     deleteInTx(java.lang.Iterable<T> entities)
      void     deleteByKey(K key)  // 刪除指定主鍵對應的實體
      void     deleteByKeyInTx(K... keys)
      void     deleteByKeyInTx(java.lang.Iterable<K> keys)

      Dao 修改

      void     update(T entity)
      void     updateInTx(T... entities)
      void     updateInTx(java.lang.Iterable<T> entities)

      Dao 其它

      void     refresh(T entity)  // 從數據庫獲取值刷新本地實體
      long     count()  // 數量

      boolean detach(T entity) // 從域中分離實體 void detachAll() // 從域中分離所有實體

      AbstractDaoSession getSession() Database getDatabase() java.lang.String getTablename() java.lang.String[] getAllColumns() java.lang.String[] getPkColumns() java.lang.String[] getNonPkColumns() Property getPkProperty() Property[] getProperties()</code></pre>

      Dao 查詢

      java.util.List<T>     loadAll()
      T     load(K key)
      T     loadByRowId(long rowId)

      QueryBuilder 查詢

      List joes = userDao.queryBuilder()  // 查詢 User
                      .where(Properties.FirstName.eq("Joe"))  // 首名為 Joe
                      .orderAsc(Properties.LastName)  // 末名升序排列
                      .list();  // 返回集合

      // Joe,>= 1970.10 QueryBuilder qb = userDao.queryBuilder(); qb.where(Properties.FirstName.eq("Joe"), qb.or(Properties.YearOfBirth.gt(1970), qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10)))); List youngJoes = qb.list();</code></pre>

      QueryBuilder<T>     queryBuilder()  // Dao

      // QueryBuilder QueryBuilder<T> where(WhereCondition cond, WhereCondition... condMore) // 條件,AND 連接 QueryBuilder<T> whereOr(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore) // 條件,OR 連接 QueryBuilder<T> distinct() // 去重,例如使用聯合查詢時 QueryBuilder<T> limit(int limit) // 限制返回數 QueryBuilder<T> offset(int offset) // 偏移結果起始位,配合limit(int)使用 QueryBuilder<T> orderAsc(Property... properties) // 排序,升序 QueryBuilder<T> orderDesc(Property... properties) // 排序,降序 QueryBuilder<T> orderCustom(Property property, java.lang.String customOrderForProperty) // 排序,自定義 QueryBuilder<T> orderRaw(java.lang.String rawOrder) // 排序,SQL 語句 QueryBuilder<T> preferLocalizedStringOrder() // 本地化字符串排序,用于加密數據庫無效 QueryBuilder<T> stringOrderCollation(java.lang.String stringOrderCollation) // 自定義字符串排序,默認不區分大小寫

      WhereCondition and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore) // 條件,AND 連接 WhereCondition or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore) // 條件,OR 連接</code></pre>

      Query 重復查詢

      // Joe,1970
      Query query = userDao.queryBuilder().where(
          Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970)
      ).build();
      List joesOf1970 = query.list();

      // Maria,1977 query.setParameter(0, "Maria"); query.setParameter(1, 1977); List mariasOf1977 = query.list();</code></pre>

      // QueryBuilder
      Query<T>     build()
      CursorQuery     buildCursor()
      CountQuery<T>     buildCount()
      DeleteQuery<T>     buildDelete()

      // Query // 設置查詢參數,從 0 開始 Query<T> setParameter(int index, java.lang.Object parameter) Query<T> setParameter(int index, java.lang.Boolean parameter) Query<T> setParameter(int index, java.util.Date parameter) void setLimit(int limit) // 限制返回數 void setOffset(int offset) // 偏移結果起始位,配合limit(int)使用

      // Query 綁定線程,執行非本線程的 Query 拋異常,調用獲取本線程 Query Query<T> forCurrentThread() // 獲取本線程 Query</code></pre>

      獲取查詢結果

      // QueryBuilder、Query
      T     unique()  // 返回唯一結果或者 null
      T     uniqueOrThrow()  // 返回唯一非空結果,如果 null 則拋異常
      java.util.List<T>     list()  // 返回結果集進內存
      // 懶加載,須在 try/finally 代碼中關閉。
      LazyList<T>     listLazy()  // 第一次使用返回結果集,所有數據使用后會自動關閉
      LazyList<T>     listLazyUncached()  // 返回虛擬結果集,數據庫讀取不緩存
      CloseableListIterator<T>     listIterator()  // 懶加載數據迭代器,不緩存,所有數據使用后會自動關閉

      // QueryBuilder、CountQuery long count() // 獲取結果數量</code></pre>

      SQL 查詢

      // QueryBuilder.where() 配合 WhereCondition.StringCondition() 實現SQL查詢
      Query query = userDao.queryBuilder()
                      .where(new WhereCondition.StringCondition("_ID IN (SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)"))
                      .build();

      // Dao.queryRawCreate() 實現SQL查詢 Query query = userDao.queryRawCreate( ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin");</code></pre>

      // Dao
      java.util.List<T>     queryRaw(java.lang.String where, java.lang.String... selectionArg)
      Query<T>     queryRawCreate(java.lang.String where, java.lang.Object... selectionArg)
      Query<T>     queryRawCreateListArgs(java.lang.String where, java.util.Collection<java.lang.Object> selectionArg)

      // WhereCondition.PropertyCondition PropertyCondition(Property property, java.lang.String op) PropertyCondition(Property property, java.lang.String op, java.lang.Object value) PropertyCondition(Property property, java.lang.String op, java.lang.Object[] values)

      // WhereCondition.StringCondition StringCondition(java.lang.String string) StringCondition(java.lang.String string, java.lang.Object value) StringCondition(java.lang.String string, java.lang.Object... values)</code></pre>

      DeleteQuery 刪除查詢

      DeleteQuery<T>     buildDelete()  // QueryBuilder

      查詢日志

      QueryBuilder.LOG_SQL = true;
      QueryBuilder.LOG_VALUES = true;

      DaoSession 增刪改查

      // DaoSession 的方法轉換成 Dao 的對應方法執行
      <T> long     insert(T entity)
      <T> long     insertOrReplace(T entity)
      <T> void     delete(T entity)
      <T> void     deleteAll(java.lang.Class<T> entityClass)
      <T> void     update(T entity)
      <T,K> T     load(java.lang.Class<T> entityClass, K key)
      <T,K> java.util.List<T>     loadAll(java.lang.Class<T> entityClass)
      <T> QueryBuilder<T>     queryBuilder(java.lang.Class<T> entityClass)
      <T,K> java.util.List<T>     queryRaw(java.lang.Class<T> entityClass, java.lang.String where, java.lang.String... selectionArgs)
      <T> void     refresh(T entity)

      進階用法

      聯合查詢

      // 芝麻街住戶
      QueryBuilder<User> queryBuilder = userDao.queryBuilder();
      queryBuilder.join(Address.class, AddressDao.Properties.userId)
                      .where(AddressDao.Properties.Street.eq("Sesame Street"));
      List<User> users = queryBuilder.list();?

      // 歐洲超過百萬人口的城市 QueryBuilder qb = cityDao.queryBuilder().where(Properties.Population.ge(1000000)); Join country = qb.join(Properties.CountryId, Country.class); Join continent = qb.join(country, CountryDao.Properties.ContinentId, Continent.class, ContinentDao.Properties.Id); continent.where(ContinentDao.Properties.Name.eq("Europe")); List<City> bigEuropeanCities = qb.list();

      // 爺爺叫林肯的人 QueryBuilder qb = personDao.queryBuilder(); Join father = qb.join(Person.class, Properties.FatherId); Join grandfather = qb.join(father, Properties.FatherId, Person.class, Properties.Id); grandfather.where(Properties.Name.eq("Lincoln")); List<Person> lincolnDescendants = qb.list();</code></pre>

      // QueryBuilder,聯合查詢
      <J> Join<T,J>     join(java.lang.Class<J> destinationEntityClass, Property destinationProperty)
      <J> Join<T,J>     join(Property sourceProperty, java.lang.Class<J> destinationEntityClass)
      <J> Join<T,J>     join(Property sourceProperty, java.lang.Class<J> destinationEntityClass, Property destinationProperty)
      <J> Join<T,J>     join(Join<?,T> sourceJoin, Property sourceProperty, java.lang.Class<J> destinationEntityClass, Property destinationProperty)

      自定義類型

      默認支持類型: byte[] 、 String 、 Date 、

      boolean 、 int 、 short 、 long 、 float 、 double 、 byte 、

      Boolean 、 Integer 、 Short 、 Long 、 Float 、 Double 、 Byte

      // enum 轉換為 Integer
      @Entity
      public class User {
          @Id
          private Long id;

      @Convert(converter = RoleConverter.class, columnType = Integer.class)
      private Role role;
      
      public enum Role {
          DEFAULT(0), AUTHOR(1), ADMIN(2);
      
          final int id; // 使用穩定的 id 來轉換,不要使用不穩定的名字和順序
      
          Role(int id) {
              this.id = id;
          }
      }
      
      public static class RoleConverter implements PropertyConverter<Role, Integer> {
          @Override
          public Role convertToEntityProperty(Integer databaseValue) {
              if (databaseValue == null) {
                  return null;
              }
              for (Role role : Role.values()) {
                  if (role.id == databaseValue) {
                      return role;
                  }
              }
              return Role.DEFAULT; // 準備一個默認值,防止數據移除時崩潰
          }
      
          @Override
          public Integer convertToDatabaseValue(Role entityProperty) {
              // 判斷返回 null
              return entityProperty == null ? null : entityProperty.id;
          }
      }
      

      }</code></pre>

      升級

      使用 DevOpenHelper 每次升級數據庫,表會刪除重建,推薦開發使用。實際使用中建立類繼承 DaoMaster.OpenHelper,實現 onUpgrade()

      public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {

      public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
          super(context, name, factory);
      }
      
      @Override
      public void onUpgrade(Database db, int oldVersion, int newVersion) {
          if (oldVersion == newVersion) {
              Log.d("onUpgrade", "數據庫是最新版本" + oldVersion + ",不需要升級");
              return;
          }
          Log.d("onUpgrade", "數據庫從版本" + oldVersion + "升級到版本" + newVersion);
          switch (oldVersion) {
              case 1:
                  String sql = "";
                  db.execSQL(sql);
              case 2:
              default:
                  break;
          }
      }
      

      }

      // 初始化使用 MySQLiteOpenHelper MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this, "notes-db", null); Database db = helper.getWritableDb(); DaoSession daoSession = new DaoMaster(db).newSession();</code></pre>

      另有升級輔助庫 GreenDaoUpgradeHelper,通過 MigrationHelper 在刪表重建的過程中,使用臨時表保存數據并還原。

      注意: MigrationHelper.migrate() ,暫時只接收 SQLiteDatabase ,不接收 Database,影響加密的使用。可修改源碼支持。

      public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {
          public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
              super(context, name, factory);
          }

      @Override
      public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          MigrationHelper.migrate(db,TestDataDao.class,TestData2Dao.class,TestData3Dao.class);
      }
      

      }

      // 初始化 MigrationHelper.DEBUG = true; //如果你想查看日志信息,請將DEBUG設置為true MySQLiteOpenHelper helper = new MySQLiteOpenHelper(this, "test.db", null); DaoMaster daoMaster = new DaoMaster(helper.getWritableDatabase());</code></pre>

      高階用法

      SQLCipher 加密

      • 使用 getEncryptedReadableDb() 和 getEncryptedWritableDb() 獲取加密的數據庫
      • 256位AES加密,會提升APK的大小
      • Robolectric 測試時,須使用非加密數據庫
      DevOpenHelper helper = new DevOpenHelper(this, "notes-db-encrypted.db");
      Database db = helper.getEncryptedWritableDb("<your-secret-password>");
      DaoSession daoSession = new DaoMaster(db).newSession();

      RxJava

      // DaoSession
      RxTransaction     rxTx()  // 返回 IO 線程下的 Observables
      RxTransaction     rxTxPlain()  // 返回無線程調度的 Observables

      // Dao RxDao<T,K> rx() RxDao<T,K> rxPlain()

      // QueryBuilder RxQuery<T> rx() RxQuery<T> rxPlain()</code></pre>

       

      來自:http://www.jianshu.com/p/4e6d72e7f57a

       

     本文由用戶 izdv7003 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
     轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
     本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!