Android轻量级ORM框架--ActiveAndroid

最近做的一个项目中,需要用到数据库,自己以前也用过 Android 自带的SQLite,但用起来很麻烦,所以 ORM 框架的出现简直就是福音啊,现在市面上主流的框架有 GreenDaoActiveAndroidORMLiteRealm 等。

先说一下什么是 ORM(来自维基百科):

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。

再说 ActiveAndroid:

ActiveAndroid 可以只使用类似 save(),delete()的方法就完成数据的保存和删除,大大简化了 Android 中数据库的操作,而且配置也是炒鸡简单。

配置

先在 Gradle 中导入:

1
2
3
4
5
repositories {
mavenCentral()
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'

导入好以后,通过以下两部配置,先是添加一些全局的设置,即数据库的名称和版本,ActiveAndroid 将从 AndroidManifest.xml 中查询他们:

AA_DB_NAME (optional) 默认为”Application.db”
AA_DB_VERSION (optional – defaults to 1) 默认为1

注意:这两个 name 不能更改。

具体如下:

1
2
3
4
5
6
7
8
<manifest ...>
<application android:name="com.activeandroid.app.Application" ...>
...
<meta-data android:name="AA_DB_NAME" android:value="Pickrand.db" />
<meta-data android:name="AA_DB_VERSION" android:value="5" />

</application>
</manifest>

注意上面 application 的 name,必须指向 ActiveAndroid 下的 Application,这一步是必须的,如果是自定义的 Application,则:

1
public class MyApplication extends com.activeandroid.app.Application { ... }

但是如果你的 Application 已经继承了其他库,而不能继承com.activeandroid.app.Application,那么你可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyApplication extends SomeLibraryApplication {
@Override
public void onCreate() {
super.onCreate();
ActiveAndroid.initialize(this);
}

@Override
public void onTerminate() {
super.onTerminate();
ActiveAndroid.dispose();
}
}

如果你想建立一个动态数据库,可以使用 Configuration 类:

1
2
3
4
5
6
7
8
public class MyApplication extends SomeLibraryApplication {
@Override
public void onCreate() {
super.onCreate();
Configuration dbConfiguration = new Configuration.Builder(this).setDatabaseName("xxx.db").create();
ActiveAndroid.initialize(dbConfiguration);
}
}

创建数据库模型

使用注解 @Table(name=”tablename”)来表示表,用注解 @Column(name=”columnname”)表示列,但要注意的是,你的类必须继承com.activeandroid.Model,ActiveAndroid 为你的表创建了一个id字段作为自增长的主键。
下面的例子中为 Item 和 Category 分别建表,项目属于种类,一个种类有多个项目。

构造函数

ActiveAndroid使用了标准的构造函数去实例化对象,如果你想自己定义一个构造函数,就必须去定义一个无参构造器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Table(name = "Items")
public class Item extends Model {
// If name is omitted, then the field name is used.
@Column(name = "Name")
public String name;

@Column(name = "Category")
public Category category;

public Item() {
super();
}

public Item(String name, Category category) {
super();
this.name = name;
this.category = category;
}
}

关系

在 Item 类中直接创建一个 Category

1
2
3
4
5
6
7
8
9
@Table(name = "Items")
public class Item extends Model {

@Column(name = "Name")
public String name;

@Column(name = "Category")
public Category category;
}

在 Category 中,通过一个辅助方法来指明与许多 Item 的关系

1
2
3
4
5
6
7
8
9
10
@Table(name = "Categories")
public class Category extends Model {
@Column(name = "Name")
public String name;

// This method is optional, does not affect the foreign key creation.这个方法是可选的,不影响外键的创建
public List<Item> items() {
return getMany(Item.class, "Category");
}
}

加速应用的启动

ActiveAndroid 通过遍历所有的文件去寻找你的模型类,如果你有许多的依赖关系,这一过程将非常缓慢。可以通过在 AndroidManifest.xml 中明确的指定你的模型类来加速这一过程。

1
2
3
<meta-data
android:name="AA_MODELS"
android:value="com.myapp.model.Item, com.myapp.model.Category" />

保存数据

插入

创建一个实例,为变量赋值,然后调用 .save()方法。

1
2
3
Category restaurants = new Category();
restaurants.name = "Restaurants";
restaurants.save();

创建一条 Item 记录,为它分配 category。

1
2
3
4
Item item = new Item();
item.category = restaurants;
item.name = "Outback Steakhouse";
item.save();

批量插入

在同一时间插入多条数据可以使用事务,调用事务可以加速大约100倍。

1
2
3
4
5
6
7
8
9
10
11
12
ActiveAndroid.beginTransaction();
try {
for (int i = 0; i < 100; i++) {
Item item = new Item();
item.name = "Example " + i;
item.save();
}
ActiveAndroid.setTransactionSuccessful();
}
finally {
ActiveAndroid.endTransaction();
}

更新数据

1
new Update(Item.class).set("").where("name=?").excute();

删除数据

三种形式去删除一条记录:

1
2
3
4
Item item = Item.load(Item.class, 1);
item.delete();
Item.delete(Item.class,1);
new Delete().from(Item.class).where("Id = ?", 1).execute();

查询数据

从数据库中随机获得一个 item

1
2
3
public static Item getRandom() {
return new Select().from(Item.class).orderBy("RANDOM()").executeSingle();
}

获得所有的 item,通过 name 排序

1
2
3
4
5
6
7
public static List<Item> getAll(Category category) {
return new Select()
.from(Item.class)
.where("Category = ?", category.getId())
.orderBy("Name ASC")
.execute();
}

数据库升级

每当你的数据库模式更新后,你都需要去增加数据库版本号,通过 Configuration 或者是 AA_DB_VERSION,如果新添加了表,ActiveAndroid 会自动添加到数据库。如果你想改变一些已经存在的表(例如添加列,或是更改一个表的名字),你就需要在 assets/migrations 目录下添加一个sql脚本NewVersion.sql,这个 NewVersion 就是 AA_DB_VERSION。
ActiveAndroid 将会执行这个脚本,当脚本名>旧的数据库版本并且<=新的版本。
假设你要添加一个列 color 给Items表,你需要去增加AA_DB_VERSION,例如原先是1,那么改为2,然后提供一个脚本 2.sql:

ALTER TABLE Items ADD COLUMN color INTEGER;
删除一个表,例如Users:

1
DROP TABLE Users;

修改表结构,
Note:Sql命令必须是大写,如果是小些,例如drop table Users,就会出错:

Error:Execution failed for task ‘:app:packageDebug’.
java.io.FileNotFoundException: G:\javaAndroid\Mine\MyApplication3\app\build\intermediates\assets\debug\migrations (拒绝访问。)

参考

ActiveAndroid—Android轻量级ORM框架

Android ORM 框架之 ActiveAndroid