ActiveAndroid 简单方便的ORM(对象关系映射)

One important thing to note is that ActiveAndroid creates an id field for your tables. This field is an auto-incrementing primary key.


对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编


ORM 对象关系映射Object Relational Mapping,简称ORM,
ORM 对象关系映射Object Relational Mapping, 简称ORM


官方的: https://github.com/pardom/ActiveAndroid/


可以参考的: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0104/2255.html


ActiveAndroid
ActiveAndroid
ActiveAndroid is an active record style ORM (object relational mapper). What does that mean exactly?
 Well, ActiveAndroid allows you to save and retrieve SQLite database records without ever writing a single SQL statement. 
Each database record is wrapped neatly into a class with methods like save() and delete().
ActiveAndroid 是一种活动记录样式的ORM(对象关系映射).这个代表什么?
就是说,ActiveAndroid 允许你去不使用一条SQL语句就可以保存和恢复SQLite数据库记录。
每一条数据库记录就是一个包裹起来变成了一个有save()delete()方法的类。

ActiveAndroid does so much more than this though. 
Accessing the database is a hassle, to say the least, in Android. 
ActiveAndroid takes care of all the setup and messy stuff, and all with just a few simple steps of configuration.
ActivieAndroid 能做的不只如此,访问数据库只是一小部分的功能,
在android 中,ActiveAndroid 处理所有的安装和复杂的事情,只需要一点配置的步骤。


---------------------------------
0:Adding The JAR
---------------------------------
If you're using Android Studio:


If you haven’t done so already, create an Android project.
Drag the jar to the libs folder of project.
Right click on the jar, and select "Add as a Library…"


---------------------------------
1:Installing with Gradle
---------------------------------
Modify your build.gradle to include:
下面的repositories 里面的内容添加到项目的build.gradle
repositories {
    mavenCentral()
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}


添加后效果如下:


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


下面的compile添加到app目录下面的build.gradlel
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'


---------------------------------
2: Configuring Your Project
---------------------------------
注意这个application 既可以在清单文件里面填写com.activeandroid.app.Application,也可以在现有的Application 里面添加初始化的语句ActiveAndroid.initialize(this)
数据库既可以在清单文件里面写,也可以在代码里面添加。


2.1:在清单文件填写:
Now that you have ActiveAndroid added to you project, you can begin your two-step configuration process! The first thing we’ll need to do is add some global settings. ActiveAndroid will look for these in the AndroidManifest.xml file. Open the AndroidManifest.xml file located at the root directory of your project. Let’s add some configuration options.


AA_DB_NAME (optional)
AA_DB_VERSION (optional – defaults to 1)
The configuration strings for my project look like this
<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>






Notice also that the application name points to the ActiveAndroid application class. This step is required for ActiveAndroid to work. If you already point to a custom Application class, just make that class a subclass of com.activeandroid.app.Application.


2.2.1如果我们之前已经自定义了Application,那么让这个Application 继承com.activeandroid.app.Application就可以了。
If you are using a custom Application class, just extend com.activeandroid.app.Application instead of android.app.Application


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


2.2.2如果我们已经继承了某个其他的Application了呢?那么直接在这里面使用ActiveAndroid.initialize(this)来进行初始化就可以了。
But what if you're already doing this to utilize another library? Simply initialize ActiveAndroid in the Application class. You may call ActiveAndroid.dispose(); if you want to reset the framework for debugging purposes. (Don’t forget to call initialize again.)


public class MyApplication extends SomeLibraryApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        ActiveAndroid.initialize(this);
    }
}
最好是把onTerminate添加上。
public class MyApplication extends SomeLibraryApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        ActiveAndroid.initialize(this);
    }
    @Override
    public void onTerminate() {
        super.onTerminate();
        ActiveAndroid.dispose();
    }
}


2.2.3还有数据库,我们也可以在代码中动态的生成,而不是在清单文件中生成。
If you want to build a database dynamically.You can use the configuration class.


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






3:创建数据库model小李子,数据库模型,通过类的方式。
小例子:
In our example we have two tables: Category and Item.
In step two you will create classes for those tables.
Don’t worry though, this part is easy too.


We'll go into more detail about setting up the database model later, but here are our classes.


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


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


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


4:创建数据库模型:
Creating the database model is easy. Just create classes named your desired table name, which have annotated fields for each of the columns.


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
There are only two important things to keep in mind. 


1:你的类必须要继承Model的类,并且成员必须是用@Column 来进行注解的
Your class must extend the Model class and your members must be annotated using @Column. 
ActiveAndroid 会将原始数据类型和关系传递给其他的表和数据类。
ActiveAndroid will handle primitive data types as well as relationships to other tables and date classes.
官方的一个词用错了,应该是data




2:id 是自动生成的自增长的主键
One important thing to note is that ActiveAndroid creates an id field for your tables. 
This field is an auto-incrementing primary key.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


结构
Constructors


ActiveAndroid uses the standard-constructor of your class to instantiate objects. If you define your own constructors you have to define a parameterless constructor as well. Look in the source code for more documentation.
ActiveAndroid 使用你的类的标准结构(其实就是无参数的构造方法)来实例化对象(object),
如果你定义了自己的构造方法,你也需要定义一个无参的构造方法。


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


关系:
Relationships


In the previous article we used the example of Categories and Items. Items belong in a Category and Categories have many Items. How do we represent that relationship with ActiveAndroid?


In the Item class we can make a direct relationship to the Category it is in by creating a Category member.


@Table(name = "Items")
public class Item extends Model {


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


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


可以通过getMany()的方法来获得List的列表,注意这里的items是一个方法。这个方法是可选的。


Similarly, the Category class can indicate it’s relationship to many Items. We do this with a helper method.


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




设置index
Setting indexes


You can set indexes on specified columns by setting index = true in the Column definition annotation.


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


    @Column(name = "Category", index = true)
    public String category;
This will create a query on both columns




下面这步很重要:
因为默认的情况下,ActiveAndroid 将找所有的文件去找模型类,那么这样的话,效率很低

那么我们可以直接去指定模型类。


Speeding up application startup


ActiveAndroid will look through all your files to find your Model classes. This process can be very slow if you have a lot of dependencies. To speed up this process, specify your Model classes explicitely in your AndroidManifest:




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


数据库的操作:增删改查:
增改Inserting and updating records


如果想要生成一条记录,只要新建一个activeandroid.Model的实例就好了,给他的属性赋值,然后调用save的方法。
To save a new record, just create a new instance of an activeandroid.Model class, assign values to its fields, and call the .save() method. 
That’s all. The save method works for both inserting and updating records.
这个save方法对于插入和更新都有用。


Here’s an example


Category restaurants = new Category();
restaurants.name = "Restaurants";
restaurants.save();
Now let’s create an Item record, and assign a category to it


Item item = new Item();
item.category = restaurants;
item.name = "Outback Steakhouse";
item.save();
Let’s add some more items.


item = new Item();
item.category = restaurants;
item.name = "Red Robin";
item.save();


item = new Item();
item.category = restaurants;
item.name = "Olive Garden";
item.save();




批量的输入
Bulk insert


To insert multiple records at the same time you can use transactions. Calls wrapped in transactions can be speed up by a factor of around 100. Here's an example:


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();
}
This takes about 40 ms wrapped in a transaction, and 4 seconds when it's not.


删除:
Deleting records


What about deleting a record? Well, to delete a single record just call the delete() method. In the following example we’ll load an Item object by Id and delete it.


Item item = Item.load(Item.class, 1);
item.delete();
Or you can delete it statically


Item.delete(Item.class, 1);
You can also use the query builder syntax


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


-----------------
查找数据:
-----------------
所有的查询的请求,在activeAndoird 中使用查询 builder的语法,或者Model.query()的方法。
注意所谓的builder的方法就是可以一直.点.点的弄下去。


All queries in ActiveAndroid use the query builder syntax, or the Model.query() method.


Let's look at some queries by adding to our model. Here's what we have so far:


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


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


It would be nice if we could get a random item from the database. Let's add a method to do that.


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




Building a query in ActiveAndroid is like building a normal SQL statement. We create a new select object, call from and pass in the Item class. We then call orderBy, passing in "RANDOM". To execute a query we call execute(), or in this case executeSingle().


If we only want to get items from a certain category, we pass in a string for our where class argument. The method would look like this:


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


-------------------
支持序列化:
-------------------


Type serializers
ActiveAndroid 默认可以处理很多类型。如果需要处理一个自定义的数据类型,有可以见到那的通过使用TypeSerializer。
ActiveAndroid handles many types by default. If the need arrises for handling a custom data type, you easily do so using TypeSerializer. The best way to learn how it works is by looking at an example. Let's consider the Date type.


当创建TypeSerializer我们必须考虑怎么将数据类型变成ActiveAndroid 可以处理的原型数据
When creating a TypeSerializer we must consider how we can reduce the Data type down to a primitive type that ActiveAndroid can handle. Dates can be converted to a Long, so let's use that type.


Here's the code used in the ActiveAndroid source for Dates.


final public class UtilDateSerializer extends TypeSerializer {
    @Override
    public Class<?> getDeserializedType() {
        return Date.class;
    }


    @Override
    public Class<?> getSerializedType() {
        return Long.class;
    }


    @Override
    public Long serialize(Object data) {
        if (data == null) {
            return null;
        }


        return ((Date) data).getTime();
    }


    @Override
    public Date deserialize(Object data) {
        if (data == null) {
            return null;
        }


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




数据库里面可以存储Long 类型的数据,但是不能存储Date类型的数据,
所以要将Date类型的数据序列化诚Long类型的数据。
如果要使用的话,需要将Long类型的数据反序列化诚Date类型的数据。







Deserialized 反序列化


第一个方法,是得到反序列化,在这个方法里面,我们返回我们正在序列化的类,在上面的例子里面,我们返回Date。
The first method we see is getDeserializedType. In this method we return the class we are serializing. For the Date TypeSerializer we return Date.class.


第二个方法,返回相反的类型,就是序列化。也就是,我们想要存储到数据库的类型。我们有一个枚举的值可以用来选择,而不是期待一个原始的类型进行返回。
The second method returns the inverse type. That is, the type we want to store in the database. Rather than expecting a literal type returned, we have an enumeration value to choose from.
我们可以在这个方法里面使用下面的枚举值INTEGER,REAL,TEXT,BLOB(像是存储图片就是使用的BLOB)
You can use the following enumeration values for this method.


public enum SQLiteType {
    INTEGER, REAL, TEXT, BLOB
}


第三个方法,将我们支持的数据类型转化为ActiveAndroid 可以存储的。在这里我们使用Date的getTime()的方法来返回一个Long类型的。
The next method transforms our supported data type into a data type ActiveAndroid can store. Here we use the getTime() method of Date to return a Long.


最后一个方法,inflate存储在数据库的数据转换为支持的数据类型。Date类型的可以构造为一个Long类型的,所以我们使用存储Long 类型的数据图返回一个Date类型的对象。
The last method inflates the data stored in the database into the supported data type. Date can be constructed with a Long, so we use the stored Long data to return a new Date object.




要使用ActiveAndroid 来登记你的自定义的类型序列化者,你需要在清单文件中申明。
To register your custom type serializers with Active Android, you need to declare them in AndroidManifest.xml.


<meta-data android:name="AA_SERIALIZERS" 
      android:value="my.package.CustomTypeSerializer,my.package.AnotherCustomeTypeSerializer" />




-------------------------------
Using the content provider
-------------------------------
使用ContentProvider。


Add method in Table annotation for set column Id name.


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


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);
        }
    });
You must also have the following provider in your AndroidManifest.xml:


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




上面的,我自己修改的ContentLoader相关的:
        mSpinner = new Spinner(this);
        mSpinner.setAdapter(new SimpleCursorAdapter(this,android.R.layout.simple_expandable_list_item_1,
                null,
                new String[]{"MyProperty"},
                new int[]{android.R.id.text1},
                0));


        getSupportLoaderManager().initLoader(0, null, new LoaderManager.LoaderCallbacks<Cursor>() {
            @Override
            public Loader<Cursor> onCreateLoader(int id, Bundle args) {
//                return null;
                return new CursorLoader(context,
                        ContentProvider.createUri(Item.class,null),
                        null,null,null,null);
            }


            @Override
            public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
                ((SimpleCursorAdapter)mSpinner.getAdapter()).swapCursor(data);
            }


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




swapCursor的方法是将性的Cursor调入内存,然后退出老的Cursor。


swapCursor:Swap in a new Cursor, returning the old Cursor. Unlike changeCursor(Cursor), the returned old Cursor is not closed.


-------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值