首页 > 代码库 > Android ORM 框架之 ActiveAndroid应用基础

Android ORM 框架之 ActiveAndroid应用基础

ActiveAndroid作为轻量级的ORM框架,在快速开发中,使用很简单,满足大部分对数据库操作不复杂的应用。

一,配置

添加依赖

build.gradle中添加:

repositories {
    mavenCentral()
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}

compile ‘com.michaelpardo:activeandroid:3.1.0-SNAPSHOT‘

项目配置

1>Application类配置:

<manifest ...>
    <application android:name="com.activeandroid.app.Application" ...>

        ...

    </application>
</manifest>

注意:应用程序的名称指向ActiveAndroid应用程序类。如果使用自定义的应用程序类,要继承com.activeandroid.app.Application而不是android.app.Application:

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

但是,如果已经有了继承其他Application类的类,需要在应用程序初始化类ActiveAndroid(如果调试中需要重置框架,调用ActiveAndroid.dispose();后初始化):

public class MyApplication extends SomeLibraryApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        ActiveAndroid.initialize(this);
    }
}

2>配置数据库名和版本名:

        <meta-data android:name="AA_DB_VERSION" android:value=http://www.mamicode.com/"5" />

    
" data-snippet-id="ext.daf1f5118d4bae054a2dd92e5b20fa11" data-snippet-saved="false" data-codota-status="done"><manifest ...>
    <application...>

        ...

        <meta-data android:name="AA_DB_NAME" android:value=http://www.mamicode.com/"Pickrand.db" />
        <meta-data android:name="AA_DB_VERSION" android:value=http://www.mamicode.com/"5" />

    </application>
</manifest>

如果想动态的创建数据库,可以这样配置:

public class MyApplication extends SomeLibraryApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        Configuration dbConfiguration = new Configuration.Builder(this).setDatabaseName("xxx.db").create();
        ActiveAndroid.initialize(dbConfiguration);
    }
}

二,创建表

创建表需要新建实体类继承Model,添加类注解@Table(name = “表名”),类成员添加@Column注解标识表里的列。 ActiveAndroid自动为表添加自增的id主键。ActiveAndroid使用标准构造函数实例化对象,如果定义有自己的构造函数,还必须定义一个无参构造函数。
如下,创建一个表Items,表中添加两列(自动添加id列),一个为String类型的Name列,一个为实体Category列:

@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;
        }
}

@Table(name = "Categories")
public class Category extends Model {
    @Column(name = "Name")
    public String name;

    ...
}

如果Category 和 Item是一对多的关系,可以在Category类中添加一个helper 方法:

@Table(name = "Categories")
public class Category extends Model {
    ...

        // helper方法, 不要影响外键创建.
    public List<Item> items() {
        return getMany(Item.class, "Category");
    }
}

指定某个列可以被索引,在其注解中添加:index = true。

@Column(name = "Name", index = true)
    public String name;

其他属性可以查询依赖包中com.activeandroid.annotation.Column。

ActiveAndroid会搜索所有的文件查找Model的子类,如果项目中有很多依赖,这个过程会花费很长时间。为了加快应用的启动速度,我们可以在清单文件中明确的指出model类,多个用逗号分开:

" data-snippet-id="ext.2e7fb879004fa8409733297b1d4b556f" data-snippet-saved="false" data-codota-status="done"><meta-data
    android:name="AA_MODELS"
    android:value=http://www.mamicode.com/"com.myapp.model.Item, com.myapp.model.Category" />

不要使用以下词语作表和列名:

ABORT               DEFAULT         INNER         REGEXP
ACTION              DEFERRABLE      INSERT        REINDEX
ADD                 DEFERRED        INSTEAD       RELEASE
AFTER               DELETE          INTERSECT     RENAME
ALL                 DESC            INTO          REPLACE
ALTER               DETACH          IS            RESTRICT
ANALYZE             DISTINCT        ISNULL        RIGHT
AND                 DROP            JOIN          ROLLBACK
AS                  EACH            KEY           ROW
ASC                 ELSE            LEFT          SAVEPOINT
ATTACH              END             LIKE          SELECT
AUTOINCREMENT       ESCAPE          LIMIT         SET
BEFORE              EXCEPT          MATCH         TABLE
BEGIN               EXCLUSIVE       NATURAL       TEMP
BETWEEN             EXISTS          NO            TEMPORARY
BY                  EXPLAIN         NOT           THEN
CASCADE             FAIL            NOTNULL       TO
CASE                FOR             NULL          TRANSACTION
CAST                FOREIGN         OF            TRIGGER
CHECK               FROM            OFFSET        UNION
COLLATE             FULL            ON            UNIQUE
COLUMN              GLOB            OR            UPDATE
COMMIT              GROUP           ORDER         USING
CONFLICT            HAVING          OUTER         VACUUM
CONSTRAINT          IF              PLAN          VALUES
CREATE              IGNORE          PRAGMA        VIEW
CROSS               IMMEDIATE       PRIMARY       VIRTUAL
CURRENT_DATE        IN              QUERY         WHEN
CURRENT_TIME        INDEX           RAISE         WHERE
CURRENT_TIMESTAMP   INDEXED         RECURSIVE     WITH
DATABASE            INITIALLY       REFERENCES    WITHOUT
                    ID

三,数据处理

保存一条新的数据,需要创建一个activeandroid.Model对象,为其成员指定值,然后其save()方法。save()执行保存和更新数据。

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

插入一条item数据,并为其指定一个category

Item item = new Item();
item.category = restaurants;
item.name = "Outback Steakhouse";
item.save();

如果插入多条数据,需要重复创建activeandroid.Model对象,然后重复执行相关操作。

要删除单条记录只需要调用delete()方法。在下面的例子中,我们将通过id加载一个对象,并将其删除:

Item item = Item.load(Item.class, 1);
item.delete();

或:

Item.delete(Item.class, 1);

也可以使用查询语法:

new Delete().from(Item.class).where("Id = ?", 1).execute();

ActiveAndroid可以使用查询语法或Model.query()方法查询数据。
获取一条随机的数据:

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

ActiveAndroid构建查询就像建立一个正常的SQL语句,创建一个新的Select对象,调用并传入item类。然后,我们调用排序依据方法,传递“随机”。要执行可以调用execute(查询),或者executeSingle()。等还有一些其他指令。
从指定的category随机获取一个item:

public static Item getRandom(Category category) {
    return new Select()
        .from(Item.class)
        .where("Category = ?", category.getId())
        .orderBy("RANDOM()")
        .executeSingle();
}

获取所有item,并按name排列:

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

事务

当一次执行多条数据时,还可以使用事务处理,会较于上面方法有很大加速。
一次插入多条数据:

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();
}

在查询Category数据时,因为每个对象中包括了一个List对象,所以,我们需要在查询出Category对象后,在把关联的List表查询一遍:

ActiveAndroid.beginTransaction();
try {
    List<Category> category = new Select().from(Category.class).limit(20).execute();
    if (category != null) {
        int len = category.size();
        for (int i = 0; i < len; i++) {
            category.get(i).items();
        }
    }
   ActiveAndroid.setTransactionSuccessful();
   } finally {
       ActiveAndroid.endTransaction();
   }

四,类型序列

ActiveAndroid默认处理多种类型。如果需要处理自定义数据类型,继承TypeSerializer,重写其方法。比如我们要将Date类型转换为long类型保存,读取的时候又直接得到Date类型:

    public final class UtilDateSerializer extends TypeSerializer {
    /**
     *返回序列的类
     */
    public Class<?> getDeserializedType() {
        return Date.class;
    }
    /**
     *返回存储到数据库中的类型
     */
    public Class<?> getSerializedType() {
        return long.class;
    }
   /**
    *将我们所使用的数据类型转换为ActiveAndroid存储的数据类型
    */
    public Long serialize(Object data) {
        if (data =http://www.mamicode.com/= null) {
            return null;
        }

        return ((Date) data).getTime();
    }
    /**
    *使存储的数据转换成使用的数据类型
    */
    public Date deserialize(Object data) {
        if (data =http://www.mamicode.com/= null) {
            return null;
        }

        return new Date((Long) data);
    }
}

然后注册自定义的序列化类型,在AndroidManifest.xml声明它们:

" data-snippet-id="ext.1ee965351c4bf65a80b47dda2b90f45c" data-snippet-saved="false" data-codota-status="done"><meta-data android:name="AA_SERIALIZERS" 
      android:value="my.package.CustomTypeSerializer,my.package.AnotherCustomeTypeSerializer" />

ActiveAndroid自带的TypeSerializer:
技术分享

五,使用content provider

1>在AndroidManifest.xml声明:

<application ...>
    <provider android:authorities="com.example" android:exported="false" android:name="com.activeandroid.content.ContentProvider" />
    ...
</application>

2>在表注解中添加id列:

@Table(name = "Items", id = BaseColumns._ID)
public class Item extends Model {...}

3>使用:

    mySpinner.setAdapter(new SimpleCursorAdapter(getActivity(),
        android.R.layout.simple_expandable_list_item_1,
        null,
        new String[] { "MyProperty" },
        new int[] { android.R.id.text1 },
        0));

    getActivity().getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<Cursor>() {
        @Override
        public Loader<Cursor> onCreateLoader(int arg0, Bundle cursor) {
            return new CursorLoader(getActivity(),
                ContentProvider.createUri(MyEntityClass.class, null),
                null, null, null, null
            );
        }

        @Override
        public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
            ((SimpleCursorAdapter)mySpinner.getAdapter()).swapCursor(cursor);
        }

        @Override
        public void onLoaderReset(Loader<Cursor> arg0) {
            ((SimpleCursorAdapter)mySpinner.getAdapter()).swapCursor(null);
        }
    });

六,数据库升级

当架构变化,需要增加数据库的版本号,需要使用配置文件,并且改变AA_DB_VERSION meta-data。如果你想改变数据库中现有的表(比如,添加一列或重命名表),要使用命名为< NewVersion >.sql的sql脚本,放进assets/migrations中,NewVersion是版本号。如果它的文件名比以前的数据库版本高,ActiveAndroid会执行它。
例如 向 Items表中添加 color列:
1>AA_DB_VERSION 增加为 2 ,并提供一个名为2.sql的脚本:

ALTER TABLE Items ADD COLUMN color INTEGER;

2>增加实体类color。

七,导入提供有的数据库

1>将数据库放进assets包中:

/myapp/src/main/assets/prepop.db

2>manifest.xml中设置AA_DB_NAME:

" data-snippet-id="ext.c4b39bc1310671cd64b62757b0d9451d" data-snippet-saved="false" data-codota-status="done"><meta-data android:name="AA_DB_NAME" android:value="prepop.db" />

3>创建android_metadata表:

CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT ‘en_US‘)

INSERT INTO "android_metadata" VALUES (‘en_US‘)

4>如果表model没有定义id列,主键重命名为默认值id,而不是_id。如果数据是被建议主键列为_id的使用,比如ListView,可以在@Table注解中添加id = “_id”:

@Table(name = "Items", id = "_id")
public class Item extends Model {
<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    Android ORM 框架之 ActiveAndroid应用基础