版权声明 2016 AlexZHOU
转载请注明本文出处
(翻译以个人理解为主,具体请看英文)
原文链接:https://github.com/Raizlabs/DBFlow/blob/master/usage/GettingStarted.md
In this section we run through how to build a simple database, table, and establish relationship between Model
.
在本节中,我们将通过Model
构建一个简单的数据库、表和建立关系。
The Ant Queen: We are curious in storing data about our ant colonies. We want to track and tag all ants for a specific colony as well as each queen Ant.
蚁后:我们好奇知道蚁群数据是怎么保存的。我们要跟踪和标记所有蚂蚁的特定群体以及每个蚁后。
We have this relationship:
我们得到这样的关系:
Colony (1..1) -> Queen (1...many)-> Ants
To initialize DBFlow, place this code in a custom Application
class (recommended):
初始化DBFlow,放置在这段代码在你自定义的 Application
类中(推荐):
public class ExampleApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
FlowManager.init(this);
}
}
Never fear, this only initializes once and it will hold onto only the Application
context even if initialized in another Context
.
别担心,这只是初始化一次而且它会守住只有应用程序,甚至使用其他Context初始化它。
Lastly, add the definition to the manifest (with the name that you chose for your custom application):
最后,定义添加到清单(对应您的自定义应用程序的名称)
<application android:name="{packageName}.ExampleApplication" ...>
application>
In DBFlow, a @Database
is a placeholder object that generate a subclass of BaseDatabaseDefinition
, which connect all tables, ModelAdapter, Views, Queries, and more under a single object. All connections are done pre-compile time, so there’s no searching, reflection, or anything else that can slow down the runtime impact of your app.
在DBFlow,@Database
是一个占位符,可以产生子类对象BaseDatabaseDefinition
,他可以连接所有Tables,ModelAdapter,Views,Queries还有更多其下的对象。所有连接都在预编译的时候完成,所以没有搜索,反射,和任何其他能减慢您的应用的运行时间。
In this example, we need to define where we store our ant colony:
在这个例子中,我们需要定义我们要把蚁群保存到哪里(说白了就是定义数据库):
@Database(name = ColonyDatabase.NAME, version = ColonyDatabase.VERSION)
public class ColonyDatabase {
public static final String NAME = "Colonies";
public static final int VERSION = 1;
}
For best practices, we create the constants NAME
and VERSION
as public, so other components we define for DBFlow can reference it later (if needed).
最好的实现,我们创建public类型的常量NAME
和 VERSION
,其他组件定义数据库工作流可以参考它后(如果需要)。
Note: If you wish to use SQLCipher please read setup here
如果你希望使用SQLCipher,请阅读setup here。
Now that we have a place to store our data for the ant colonies, we need to explicitly define how the underlying SQL data is stored and what we get is a Model
that represents that underlying data.
现在,我们有地方去存储我们的蚁群数据了,我们需要明确定义 Model
来保存数据和展示数据。
We will start and go top-down within the colony. There can be only one queen per colony. We define our database objects using the ORM (object-relational mapping) model. What we do is mark each field we want represented as a database column in a class that corresponds to an underlying database table.
我们将从上到下理解蚁群关系。只有一个蚁后在一个蚁群里面。我们使用ORM模式定义我们的数据库对象。我们将要做的是标志每一个字段在类中表现的数据表列并通知对应的数据库表。
In DBFlow, anything that represents an object that interacts with the database using ORM must implement Model
. The reason for an interface vs. a baseclass ensures that other kinds of Model
such as views/virtual tables can conform to the same protocol and not rely on one base class to rule them all. We extend BaseModel
as a convenience for the standard table to Model
class. Also, if not forced to at least an interface, this prevents passing in objects not meant for the methods they belong to.
在DBFlow中,任何要使用ORM实现数据库交互的都必须实现接口 Model
。基类统一接口的原因是要确定他们都是 Model
,像那些views/virtual tables 可以同意使用协议和没有依赖在一个子类上去规范他们。我们一般继承 BaseModel
作为一个便利的标准表和 Model
类。当然,如果不是强制的至少一个接口,这可以防止在对象中不属于他们的方法。
To properly define a table we must:
要正确定义一个表,我们必须:
Mark the class with @Table
annotation
Point the table to the correct database, in this case ColonyDatabase
Define at least one primary key
The class and all of its database columns must be package private, public
, or private (with corresponding getters and setters), so that the classes generated from DBFlow can access them.
(大意如下:)
使用 @Table
注释标记类
将表链接正确的数据库,例如ColonyDatabase
至少定义个一主键
类及其所有数据库中的列(model中的变量)必须用 public
或private,private的必须有(getter和setter方法)。这样从DBFlow生成的类可以访问它们。
The basic definition of Queen
we can use is:
我们可以这样定义一个基础的 Queen
表:
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
@PrimaryKey(autoincrement = true)
long id;
@Column
String name;
}
So we have a queen ant definition, and now we need to define a Colony
for the queen.
这样我们定义了一个蚁后,现在我们需要给蚁后定义一个 Colony
。
@ModelContainer // more on this later.
@Table(database = ColonyDatabase.class)
public class Colony extends BaseModel {
@PrimaryKey(autoincrement = true)
long id;
@Column
String name;
}
Now that we have a Queen
and Colony
table, we want to establish a 1-1 relationship. We want the database to care when data is removed, such as if a fire occurs and destroys the Colony
. When the Colony
is destroyed, we assume the Queen
no longer exists, so we want to “kill” the Queen
for that Colony
so it no longer exists.
现在我们拥有一个有 Queen
和 Colony
的表,我们需要建立1-1的关系。我们想要数据知道当数据被删除,比如发生火灾 Colony
。当 Colony
被销毁时,我们的 Queen
也将消失,当然,我们杀死 Queen
的同时, Colony
也将不存在。
To establish the connection, we will define a Foreign Key that the child, Queen
uses:
为了建立他们的关系,我们将会定义一个外键作为Child:
@ModelContainer
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
//...previous code here
@Column
@ForeignKey(saveForeignKeyModel = false)
Colony colony;
}
Defining the Foreign Key as a Model
will automatically load the relationship when loading from the database using a query on the value of the reference in that column. For performance reasons we default saveForeignKeyModel=false
to not save the parent Colony
when the Queen
object is saved.
为 Model
定义外键的时候,查询数据库的时候,该外键的值会被加载。处于性能原因,我们定义 saveForeignKeyModel=false
不保存 Colony
当 Queen
对象保存是时候。
If you wish to keep that pairing intact, set saveForeignKeyModel=true
.
如果你想保持这种配对完好,设置 saveForeignKeyModel=true
。
As of 3.0, we no longer need to explicitly define the @ForeignKeyReference
for each referenced column. DBFlow will add them automatically to the table definitions based on the @PrimaryKey
of the referenced tables. They will appear in the format of {foreignKeyFieldName}_{referencedColumnName}
.
在3.0的版本中,我们不再要求每个列需要声明 @ForeignKeyReference
。DBFlow会自动将它们添加到表定义中,基于引用表的@PrimaryKey。它们将出现在格式 {foreignKeyFieldName}_{referencedColumnName}
。
Now that we have a Colony
with a Queen
that belongs to it, we need some ants to serve her!
现在我们有 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 queenForeignKeyContainer;
/** * Example of setting the model for the queen. */
public void associateQueen(Queen queen) {
queenForeignKeyContainer = FlowManager.getContainerAdapter(Queen.class).toForeignKeyContainer(queen);
}
}
We have the type
, which can be “worker”, “mater”, or “other”. Also if the ant is male or female.
我们需要有 type
,哪个可以当”worker”, “mater” 或者 “other” ,当然还有男女之分。
We use a ForeignKeyContainer
in this instance, since we can have thousands of ants. For performance reasons this will “lazy-load” the relationship of the Queen
and only run the query on the DB for the Queen
when we call toModel()
. With this said, in order to set the proper values on the ForeignKeyContainer
you should call its generated method for converting itself into a ForeignKeyContainer
via FlowManager.getContainerAdapter(Queen.class).toForeignKeyContainer(queen)
.
我使用 ForeignKeyContainer
在这个实例中,以为我们有成千上万的蚂蚁。处于性能考虑, Queen
将会延迟加载,只有当我们调用toModel()
去查询数据库的时候,数据库才会找出对应的 Queen
。与此说,为了在 ForeignKeyContainer
上设置适当的值,你应该通过调用其生成的方法 FlowManager.getContainerAdapter(Queen.class).toForeignKeyContainer(queen)
为自己转换成 ForeignKeyContainer
。
Since ModelContainer
usage is not generated by default, we must add the @ModelContainer
annotation to the Queen
class in order to use for a ForeignKeyContainer
.
由于 ModelContainer
在默认情况下不会使用,我们需要添加 @ModelContainer
注解在
Queen
类中才能使用 ForeignKeyContainer
。
Lastly, using @ForeignKeyContainer
can prevent circular references. If both the Queen
and Colony
referenced each other by Model
, we would run into a StackOverFlowError
, since they both would try to load each other out of the database.
最后,使用 @ForeignKeyContainer
可以防止循环引用,如果 Queen
和 Colony
互相引用,我们会碰上的 StackOverflowError
,因为他们都将尝试从数据库加载对方中。
Next, we establish the 1-to-many relationship by lazy-loading the ants, since we may have thousands, if not, millions stored:
接下来,我们延迟加载建立1对多的蚂蚁关系,当蚂蚁数量成千上万时,甚至是一百万计数:
@ModelContainer
@Table(database = ColonyDatabase.class)
public class Queen extends BaseModel {
//...
// needs to be accessible for DELETE
List ants;
@OneToMany(methods = {OneToMany.Method.SAVE, OneToMany.Method.DELETE}, variableName = "ants")
public List getMyAnts() {
if (ants == null || ants.isEmpty()) {
ants = SQLite.select()
.from(Ant.class)
.where(Ant_Table.queenForeignKeyContainer_id.eq(id))
.queryList();
}
return ants;
}
}
If you wish to lazy-load the relationship yourself, specify OneToMany.Method.DELETE
and SAVE
instead of ALL
. If you wish not to save them whenever the Queen
’s data changes, specify DELETE
and LOAD
only.
如果你想给自己懒加载,指定 OneToMany.Method.DELETE
和 SAVE
,代替 ALL
。如果每当 Queen
的数据变化时候,您不希望保存,那么只指定 DELETE
和 LOAD
。
(学习DBFlow的时候顺便坐了一下翻译,哪里写的不对的地方请指出)