DBFlow使用说明(1)快速入门

在这一章节中,我们快速浏览一下如何创建一个简单的数据库、表和建立Model 之间的关系。
蚂蚁王国 :我们打算存储关于蚁群的数据。我们想要追踪和标记某个蚁群的所有蚂蚁和蚁后。
蚁群的关系是这样的:
蚁群(1:1) ——> 蚁后(1:多)——>蚂蚁

配置数据库

为了初始化DBFlow,建议将下面的代码放到Application 类里。

public class ExampleApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        FlowManager.init(this);
    }
}

不要担心,这只是一个初始化的操作。即使你在其他Context(Activity…) 中初始化她,她也将只持有Application 的context。
最后,不要忘了把自己继承的Application放到manifest

<application  android:name="{packageName}.ExampleApplication" ...>
</application>

定义数据库

在DBFlow里,使用@Database 注解便会产生一个BaseDatabaseDefinition 的一个子类,只在这一个Object 里将连接所有的tablesModelAdapterViewsQueries 等等。
在这个例子里,我们需要定义我们存储我们蚂蚁群族的的数据库:

@Database(name = ColonyDatabase.NAME, version = ColonyDatabase.VERSION)
public class ColonyDatabase {
  public static final String NAME = "Colonies";
  public static final int VERSION = 1;
}

最好创建两个常量NAMEVERSION,以便我们后面定义DBFlow的其他组件时引用它们。
Note: 如果你想要使用 SQLCipher 请阅读 setup here

创建我们的表并建立表关系

现在我们已经有了一个存储我们蚁群数据的数据库,我们还要明确我们的基础表如何存储,那么我们需要有一个能够体现基础数据的Model

蚁后表

我们将开始在蚁群里的探索咯!一个蚁群只可能有一个蚁后。我们使用对象关系映射来定义我们的数据对象。一个class 对应着一个表,我们可以标记class 的每一个字段代表我们数据表里的一列。在DBFlow,所有与数据库表进行关系映射的object 类,必须实现Model 类(原因大概是说基类里定义里一些操作数据的规则)。继承BaseModel 类就可以方便地建立一个标准的表啦。
正确地定义一个表的姿势:
1. 使用@Table 注解标记一个类。
2. 指出这个表所属的数据库。就像下面的ColonyDatabase
3. 至少定义一个主键。
4. 这个类和她所有的对应数据库列的字段必须是包级私有privatepublic 或者private(对应要有getters和setters),以便DBFlow编译时生成这些类并使用它们。
我们可以把蚁后Queen 大概定义成这样:

@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
  @PrimaryKey(autoincrement = true)
  long id;
  @Column
  String name;
}

那么我们有了蚁后的定义,现在我们需要为蚁后定义她的蚁群Colony

@ModelContainer // more on this later.
@Table(database = ColonyDatabase.class)
public class Colony extends BaseModel {
  @PrimaryKey(autoincrement = true)
  long id;
  @Column
  String name;
}

现在我们有了一蚁后和蚁群表,我们要建立一个1:1映射的关系。我们想要这个数据库关注数据的删除,例如一个火灾发生了,烧掉了这个蚁群 Colony 。当Colony 被销毁了,我们认为蚁后也不存在了;如果我们”杀死“了这个蚁后那么她的蚁群也不再有了。

1:1 关系

为了建立这个关系,我们将定义这个节点的外键。蚁后Queen :

@ModelContainer
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
  //...previous code here
  @Column
  @ForeignKey(saveForeignKeyModel = false)
  Colony colony;
}

使用Model 作为外键,这样当从数据库里查询某列的某个值时,将可以自动加载这个关系。出于性能的考虑,我们默认把 savaForeignkeyModel=false ,这样当保存 Queen 对象时,将不会保存Colony . 如果你想保持这对值的变化影响,记得设置saveForeignkeyModel =true .

note:
在3.0版本中,我们不在需要明确给每个引用列定义@ForeignkeyReference ,DBFlow将基于@PrimaryKey 标记的引用表的类自动添加他们到表的定义里。 他们将以{foreignKeyFieldName}_{referencedColumnName} 的格式出现。(写好之后要rebuild project一下)

蚂蚁表和1:多

现在我们有了一个蚁群Colony 和属于它的蚁后Queen ,我们还需要一些蚂蚁类服侍蚁后。

@Table(database = ColonyDatabase.class)
public class Ant extends BaseModel {
  @PrimaryKey(autoincrement = true)
  long id;
  @Column
  String type;
  @Column
  boolean isMale;
  @ForeignKey(saveForeignKeyModel = false)
  ForeignKeyContainer<Queen> queenForeignKeyContainer;
  /** * Example of setting the model for the queen. */
  public void associateQueen(Queen queen) {
    queenForeignKeyContainer = FlowManager.getContainerAdapter(Queen.class).toForeignKeyContainer(queen);
  }
}

我们定义了type 字段,它可能是干活的蚂蚁、产卵的蚂蚁或者其他。也定义了isMale 字段表示是男的还是女的。
在这个例子里,因为可能有很多很多蚂蚁,所以我们使用了 ForeignkeyContainer 。出于性能的考虑,这样可以延迟加载与其关联的 Queen ,当我们调用toModel 对Queen进行数据库查询时才会执行加载。基于这个原因,为了给ForeignKeyContainer 设置合适的值,你应该凭借 FlowManager.getContainerAdapter(Queen.class).toForeignKeyContainer(queen) 。调用它生成的方法并转换它到ForeignnKeyContainer 里。
因为ModelContainer 默认是不会产生的,为了使用ForeignKeyContainer我们必须添加注解到Queen 类。

最后,使用@ForeignKeyContainer 可以避免循环的引用。如果QueenColony 都使用Model 进行里关联引用,那我们将内存泄漏了,因为他们都在尝试从数据库里加载对方。

接着,我们通过延迟加载这些蚂蚁的方式建立1:多的关系,因为我们有几千只,不,也可能是几百万只蚂蚁要储存。

@ModelContainer
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
  //...
  // needs to be accessible for DELETE
  List<Ant> ants;
  @OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "ants")
  public List<Ant> getMyAnts() {
    if (ants == null || ants.isEmpty()) {
            ants = SQLite.select()
                    .from(Ant.class)
   .where(Ant_Table.queenForeignKeyContainer_id.eq(id))
                    .queryList();
    }
    return ants;
  }
}

如果你不希望延迟加载你建立的关系,指定用OneToMany.Method.DELETESAVE 来代替ALL 。如果Queen 的数据什么时光变化,你都不希望保存他们,那么你只要使用DELETE and LOAD 来替换下。

NOTE:为啥翻译这个说明文呢?
1. 项目里打算使用DBFlow。
2. 做开发快两年了,也打算写博客总结一下,写试试是什么个套路。
3. Markdown语法不熟,练练手。
4. 温习一下英语啦。
明天接着搞喽!

你可能感兴趣的:(数据库,android,DBFlow)