开始
本章我们将学习如何建立一个数据库、表单和Model
之间的联系。
蚂蚁女皇:我们的教程将以蚂蚁王国为例,我们将建立 蚂蚁领地Colony
、蚂蚁女王Queen
、蚂蚁Ant
之间的关系表。
它们的关系如下:
Colony (1..1) -> Queen (1...many)-> Ants
初始化DBFlow
初始化DBFlow的操作,包括打开数据库、进行数据迁移和创建的操作都需要在自定义的Application
中:
public class ExampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
FlowManager.init(this);
}
}
当然,自定义的Application需要在AndroidManifest.xml
文件中声明:
<application
android:name="{packageName}.ExampleApplication"
...>
</application>
创建我们的数据库
在DBFlow中,通过Table类中声明对数据库类的连接来产生交互,并生成相应的代码。(In DBFlow, databases are placeholder objects that generate interactions from which tables "connect" themselves to.)
我们需要定义一个蚂蚁领地Colony
的数据库来保存我们的小蚂蚁们:
@Database(name = ColonyDatabase.NAME, version = ColonyDatabase.VERSION)
public class ColonyDatabase {
public static final String NAME = "Colonies";
public static final int VERSION = 1;
}
作为一种推荐的写法,我们定义了NAME
和VERSION
两个公共常量,以方便我们定义的其他DBFlow组件能够在之后引用到这两个属性(如果需要的话)。
Note: 如果你希望使用 SQLCipher 对数据库进行加密的话,可以阅读 数据库加密 章节。
创建表并建立关系
现在我们有了一个地方可以创建我们的蚂蚁领地Colony
了,但还需要建立Model
来表示我们希望底层数据被如何保存。
蚂蚁女王的表(Table)
现在我们将会从上至下地建立我们的蚂蚁领地Colony
,目前我们每个领地里只有一个女王。我们将会通过ORM(object-relational mapping)的方式建立数据库,这意味着这些Model中的每一项属性都将被映射为数据表中的一列。
在DBFlow中,每个与数据库连接的ORM对象类都必须继承Model
接口。这是为了确保这些对象都能有相同的一些方法。通常为了方便我们继承BaseModel
类,这个类也是Model
的标准实现。
一个正确的数据表类需要以下几项:
- 对类添加
@Table
注解 - 声明所连接的数据库类,这里是
ColonyDatabase
。 - 定义至少一个主键。
- 这个类和这个类中数据库相关列的修饰符必须是包内私有或者
public
。 - 这样生成的
_Adapter
类能够访问到它。
NOTE: 列(Column)属性可以是private
,但这样就必须指定公有public
的getter和setter方法。
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
@PrimaryKey(autoincrement = true)
long id;
@Column
String name;
}
现在我们有了一个蚂蚁女王Queen
,还需要为我们的女王建立一个领地Colony
。
蚂蚁领地的表(Table)
@ModelContainer
@Table(database = ColonyDatabase.class)
public class Colony extends BaseModel {
@PrimaryKey(autoincrement = true)
long id;
@Column
String name;
}
我们有了一个女王Queen
和一个领地Colony
,我们希望给他们建立一个一对一的关系。
我们希望当一个数据被移除,比如如果有一场大火烧毁了一个蚂蚁领地Colony
,那么这个领地的女王Queen
也活不长了,所以我们希望能“杀掉”与这个领地Colony
相关联的女王Queen
的数据。
1-1关系
为了建立关系,我们将会定义一个外键:
@ModelContainer
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
//...previous code here
@Column
@ForeignKey(saveForeignKeyModel = false)
Colony colony;
}
定义了外键的Model
将会在载入数据库时通过查询自动将外键引用的值保存在这里。对于性能有要求的话可显式设置saveForeignKeyModel=false
使Queen
对象保存时不会保存对应的Colony
对象。
在3.0版本中,我们不再需要显式设置@ForeignKeyReference
来规定列属性了,DBFlow会自动分析和生成。
对于被用于ForeignKeyContainer
属性的Model
类,@ModelContainer
注解是必须的。因为ForeignKeyContainer
的实现需要生成一些必须的额外代码。
蚂蚁表(Table)与一对多关系
我们有了领地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
来保存外键。这是一种为性能优化的懒加载(lazy-load),只有在调用ForeignKeyContainer
的toModel()
方法时才会对数据库执行实际的查询。
为了使用ForeignKeyContainer
,我们需要给Queen
添加@ModelContainer
注解以生成相应的额外代码。
接下来我们可以通过懒加载添加一对多的关系了:
@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.DELETE
和 SAVE
替换为 ALL
。
如果你希望无论Queen
的数据如何变化它们都不会保存,只需要设置DELETE
和LOAD
。